2015-10-03 304 views
0

我在Prolog中很新鮮。我試圖編寫一個謂詞來查找最大值及其整數列表的索引。即max_list([2,3,4], MAX, INDEX)將收益MAX=4,INDEX=2查找列表中的最大元素及其索引 - Prolog

謝謝你的回覆〜我的道歉!這是我第一次在stackoverflow中提問。我可以編寫一個謂詞來查找列表的最大值或最小值,但我不知道如何獲取列表中值的確切位置。我只是想理解答案。

+1

你需要顯示的嘗試,並解釋你遇到了哪些問題 –

+0

哪種方案(S)你期待' - max_list([1,2,1? ],Max,Index)。 – repeat

回答

2

我沒有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). 
+1

你說得對。現在修復它。 – Limmen

+0

s(X):好吧,現在好了! – repeat

+0

謝謝〜這個解決方案很容易理解! –

1

另一種方法,不是很有效,但更多的「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). 
+1

s(X):好的!而不是'\ +((member(N,Lst),N> Max)''可以使用'maplist(> =(Max),Lst)'。 (這不是100%等效,但允許使用[tag:clpfd]而不是普通的Prolog整數算術......) – repeat

3

使用 ...

:- 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) :- 
        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. 
    
  2. 禁用算術表達式,我們可以結合使用length/2ins/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的問題翅膀算術表達式)不限於
當使用普通的Prolog算術謂詞如is/2和朋友時,它也存在。

+1

非常優雅和通用的解決方案! – mat

+0

謝謝!你的回答和解釋非常清楚! –

2

上joel76答案的變化:

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