2015-10-03 260 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). 
相关问题