我在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