我在Prolog中很新鲜。我试图编写一个谓词来查找最大值及其整数列表的索引。即max_list([2,3,4], MAX, INDEX)
将收益MAX=4
,INDEX=2
查找列表中的最大元素及其索引 - Prolog
谢谢你的回复〜我的道歉!这是我第一次在stackoverflow中提问。我可以编写一个谓词来查找列表的最大值或最小值,但我不知道如何获取列表中值的确切位置。我只是想理解答案。
我在Prolog中很新鲜。我试图编写一个谓词来查找最大值及其整数列表的索引。即max_list([2,3,4], MAX, INDEX)
将收益MAX=4
,INDEX=2
查找列表中的最大元素及其索引 - Prolog
谢谢你的回复〜我的道歉!这是我第一次在stackoverflow中提问。我可以编写一个谓词来查找列表的最大值或最小值,但我不知道如何获取列表中值的确切位置。我只是想理解答案。
我没有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).
另一种方法,不是很有效,但更多的“prologish”是说: 列表的最大值是多少?它是列表中的成员,并且此列表中的其他成员不超过最大值! 所以:
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):好的!而不是'\ +((member(N,Lst),N> Max)''可以使用'maplist(> =(Max),Lst)'。 (这不是100%等效,但允许使用[tag:clpfd]而不是普通的Prolog整数算术......) – repeat
使用clpfd ...
:- use_module(library(clpfd)).
... meta-predicatemaplist/2
和nth0/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
...
编辑:什么算术表达式?
我们可以允许通过增加一个额外的目标(#=)/2
使用算术表达式:
zs_maximum_at(Zs,Expr,Pos) :- maplist(#>=(Max),Zs), nth0(Pos,Zs,Expr), Expr #= Max.
现在我们可以运行查询,如下面一但失去单调性(参见this clpfd manual)!
?- zs_maximum_at([0+1,1+1,2-0,3-1,1+0],M,I). I = 1, M = 1+1 ; I = 2, M = 2-0 ; I = 3, M = 3-1 ; false.
要禁用算术表达式,我们可以结合使用length/2
与ins/2
:
zs_maximum_at(Zs,Max,Pos) :- length(Zs,_), Zs ins inf..sup, maplist(#>=(Max),Zs), nth0(Pos,Zs,Max).
运行上面的查询再次,我们现在得到:
?- zs_maximum_at([0+1,1+1,2-0,3-1,1+0],M,I). ERROR: Type error: `integer' expected, found `0+1' (a compound)
注(allo的问题翅膀算术表达式)不限于clpfd。
当使用普通的Prolog算术谓词如is/2
和朋友时,它也存在。
非常优雅和通用的解决方案! – mat
谢谢!你的回答和解释非常清楚! –
上joel76答案的变化:
max_list(L, M, I) :- nth0(I, L, M), \+ (member(E, L), E > M).
你需要显示的尝试,并解释你遇到了哪些问题 –
哪种方案(S)你期待' - max_list([1,2,1? ],Max,Index)。 – repeat