【问题标题】:Find the max element and its index in a list - Prolog在列表中查找最大元素及其索引 - Prolog
【发布时间】:2015-10-04 01:59:01
【问题描述】:

我对 Prolog 很陌生。我正在尝试编写一个谓词来查找最大值及其整数列表的索引。即max_list([2,3,4], MAX, INDEX) 将产生MAX=4, INDEX=2

谢谢你的回复~我很抱歉!这是我第一次在stackoverflow中提问。我可以编写一个谓词来查找列表的最大值或最小值,但我不知道如何获得该值在列表中的确切位置。我只是想理解答案。

【问题讨论】:

  • 你需要展示一个尝试并解释你遇到了什么问题
  • 您希望?- max_list([1,2,1],Max,Index). 有哪些解决方案?

标签: list prolog


【解决方案1】:

使用 ...

:- use_module(library(clpfd)).

...、 maplist/2nth0/3 我们定义:

zs_maximum_at(Zs,Max,Pos) :-
   maplist(#>=(Max),Zs),
   nth0(Pos,Zs,Max).

这是 OP 给出的查询:

?- zs_maximum_at([2,3,4],M,I).
I = 2, M = 4.

好的! ...最一般的查询怎么样?

?- zs_maximum_at(Zs,M,I).
  Zs = [M], I = 0, M in inf..sup
; Zs = [ M,_B], I = 0, M #>= _B
; Zs = [_A, M], I = 1, M #>= _A
; Zs = [ M,_B,_C], I = 0, M #>= _B, M #>= _C
; Zs = [_A, M,_C], I = 1, M #>= _A, M #>= _C
; Zs = [_A,_B, M], I = 2, M #>= _A, M #>= _B
; Zs = [ M,_B,_C,_D], I = 0, M #>= _B, M #>= _C, M #>= _D
; Zs = [_A, M,_C,_D], I = 1, M #>= _A, M #>= _C, M #>= _D
...

编辑:算术表达式怎么样?

  1. 我们可以允许通过添加一个额外的目标(#=)/2来使用算术表达式:

    zs_maximum_at(Zs,Expr,Pos) :- 地图列表(#>=(最大),Zs), nth0(Pos,Zs,Expr), 经验 #= 最大。

    现在我们可以运行如下查询,但会失去单调性(参见this clpfd manual)!

    ?- zs_maximum_at([0+1,1+1,2-0,3-1,1+0],M,I)。 我 = 1, M = 1+1 ;我 = 2, M = 2-0 ;我 = 3, M = 3-1 ;错误的。
  2. 禁用算术表达式,我们可以将length/2ins/2 结合使用:

    zs_maximum_at(Zs,Max,Pos) :- 长度(Zs,_), Zs ins inf..sup, 地图列表(#>=(最大),Zs), nth0(Pos,Zs,Max)。

    再次运行上面的查询,我们现在得到:

    ?- zs_maximum_at([0+1,1+1,2-0,3-1,1+0],M,I)。 错误:类型错误:预期为“整数”,发现“0+1”(复合)

请注意,问题(是否允许算术表达式)不仅限于
在使用普通的 Prolog 算术谓词(如 is/2 和朋友)时也会出现此问题。

【讨论】:

  • 非常优雅和通用的解决方案!
  • 谢谢!你的回答和解释很清楚!
【解决方案2】:

joel76 答案的变体:

max_list(L, M, I) :- nth0(I, L, M), \+ (member(E, L), E > M).

【讨论】:

【解决方案3】:

我自己不是 Prolog 专家,所以这可能不是最漂亮的解决方案,但这个谓词应该做你想做的事:

max_list([X|Xs],Max,Index):-
    max_list(Xs,X,0,0,Max,Index).

max_list([],OldMax,OldIndex,_, OldMax, OldIndex).
max_list([X|Xs],OldMax,_,CurrentIndex, Max, Index):-
    X > OldMax,
    NewCurrentIndex is CurrentIndex + 1,
    NewIndex is NewCurrentIndex,
    max_list(Xs, X, NewIndex, NewCurrentIndex, Max, Index).
max_list([X|Xs],OldMax,OldIndex,CurrentIndex, Max, Index):-
    X =< OldMax,
    NewCurrentIndex is CurrentIndex + 1,
    max_list(Xs, OldMax, OldIndex, NewCurrentIndex, Max, Index).

【讨论】:

  • s(X):好的,现在好多了!
  • 谢谢~这个解决方法通俗易懂!
【解决方案4】:

另一种方法,不是很有效,但更“序言”是说: 列表的最大值是多少?它是列表的成员,并且此列表中没有其他成员大于最大值! 所以:

max_list(Lst, Max, Ind) :-
   member(Max, Lst),
   \+((member(N, Lst), N > Max)),
   % Now, with SWI-Prolog, (may be with other Prolog)
   % nth0/3 gives you the index of an element in a list
   nth0(Ind, Lst, Max).

【讨论】:

  • s(X):好的!可以使用maplist(&gt;=(Max),Lst) 代替\+((member(N,Lst), N &gt; Max))。 (这不是 100% 等效的,但允许使用 clpfd 代替普通的 Prolog 整数运算......)
猜你喜欢
  • 1970-01-01
  • 2020-12-05
  • 2011-09-05
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
  • 2015-10-24
相关资源
最近更新 更多