2016-05-05 37 views
0

我知道序言沒有返回值,但我需要更新一些變量的值,並用該程序獲得它在控制檯:序言「如何返回值」

max(A,B,C) :- (A>B -> C is A ; C is B).             
maxAltura([],RES). 
maxAltura([c(X,Y)|[]],RES) :- max(RES,Y, SUM). 
maxAltura([c(X,Y)|R1],RES) :- RES>Y, maxAltura(R1,RES). 
maxAltura([c(X,Y)|R1],RES) :- RES<Y, maxAltura(R1,Y). 
maxAltura([c(X,Y)|R1],RES) :- RES=:=Y, maxAltura(R1,Y). 

它只是需要一個列表的元組,並給出了這些tupes的第二個元素的最大值。

這是我的輸出

maxAltura([c(1,8),c(5,0),c(6,4),c(10,0),c(11,10),c(12,0)],0). 
    Call: (7) maxAltura([c(1, 8), c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 0) ? creep 
    Call: (8) 0>8 ? creep 
    Fail: (8) 0>8 ? creep 
    Redo: (7) maxAltura([c(1, 8), c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 0) ? creep 
    Call: (8) 0<8 ? creep 
    Exit: (8) 0<8 ? creep 
    Call: (8) maxAltura([c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Call: (9) 8>0 ? creep 
    Exit: (9) 8>0 ? creep 
    Call: (9) maxAltura([c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Call: (10) 8>4 ? creep 
    Exit: (10) 8>4 ? creep 
    Call: (10) maxAltura([c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Call: (11) 8>0 ? creep 
    Exit: (11) 8>0 ? creep 
    Call: (11) maxAltura([c(11, 10), c(12, 0)], 8) ? creep 
    Call: (12) 8>10 ? creep 
    Fail: (12) 8>10 ? creep 
    Redo: (11) maxAltura([c(11, 10), c(12, 0)], 8) ? creep 
    Call: (12) 8<10 ? creep 
    Exit: (12) 8<10 ? creep 
    Call: (12) maxAltura([c(12, 0)], 10) ? creep 
    Call: (13) max(10, 0, _G4361) ? creep 
    Call: (14) 10>0 ? creep 
    Exit: (14) 10>0 ? creep 
    Call: (14) _G4359 is 10 ? creep 
    Exit: (14) 10 is 10 ? creep 
    Exit: (13) max(10, 0, 10) ? creep 
    Exit: (12) maxAltura([c(12, 0)], 10) ? creep 
    Exit: (11) maxAltura([c(11, 10), c(12, 0)], 8) ? creep 
    Exit: (10) maxAltura([c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Exit: (9) maxAltura([c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Exit: (8) maxAltura([c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 8) ? creep 
    Exit: (7) maxAltura([c(1, 8), c(5, 0), c(6, 4), c(10, 0), c(11, 10), c(12, 0)], 0) ? creep 
true . 

正如你可以看到它保持10最大值,巫婆它是正確的,我需要像MAX = 10。爲什麼只是讓我真實?

回答

1

這個簡化的版本綁定最大作爲最後一個參數。

max(A,B,C) :- A>B -> C is A ; C is B. 

maxAltura([c(_,Y)],Y). 
maxAltura([c(_,Y)|R1],RES) :- maxAltura(R1,T), max(T,Y,RES). 

注意,最大/ 3是沒用的:你可以寫

maxAltura([c(_,Y)|R1],RES) :- maxAltura(R1,T), RES is max(T,Y). 

而且,與庫(aggregate),可以進一步簡化:

maxAltura(L,MaxY) :- aggregate(max(Y), X^member(c(X,Y),L), MaxY). 
2

你可以改變給定解決方案通過使用庫(clpfd)在兩個方向上工作。只要列表被充分實例化,/ 2和>/2都可以正常工作,但只要嘗試將它們用於非綁定變量,就會遇到麻煩。考慮下面的例子:

?- maxAltura(L,M). 
L = [c(_A,M)] ? ; 
    ERROR at clause 1 of user:max/3 !! 
    INSTANTIATION ERROR- =:=/2: expected bound value 

幸運的是,這可以通過使用clpfd來彌補。在我原來的答案,我建議簡單地替換爲/ 2和#=/2和#>像這樣在最大/ 3>/2:

:- use_module(library(clpfd)). 

max(A,B,C) :- A#>B -> C#= A ; C#= B. 

% use @CapelliC's maxAltura/2 here 

然而,正如@mat指出並@false在這些評論產生了太特定/不完整的答案。因此,我建議你寧願定義最大/ 3在評論中建議,如:

:- use_module(library(clpfd)). 

max(A,B,C) :- max(A,B) #= C. 

% use @CapelliC's maxAltura/2 here 

你使用還是這個例子查詢按預期工作:

?- maxAltura([c(1,8),c(5,0),c(6,4),c(10,0),c(11,10),c(12,0)],M). 
M = 10 ? ; 
no 

有兩種觀點,現在是變量上面的查詢也可以使用:

?- maxAltura(L,M). 
L = [c(_A,M)] ? ; 
L = [c(_A,_B),c(_C,_D)], 
M#>=_B, 
M#=max(_D,_B), 
M#>=_D ? ; 
L = [c(_A,_B),c(_C,_D),c(_E,_F)], 
M#>=_B, 
M#=max(_G,_B), 
M#>=_G, 
_G#>=_D, 
_G#>=_F, 
_G#=max(_F,_D) ? 
... 
+1

您現在在最常見的情況下也能得到答案,這非常好!但是,他們目前仍然過於具體:由於不太承諾,你在最普遍的情況下就失去了解決方案。一個很好的聲明性的解決方案是寫'max(A,B,C): - max(A,B)#= C.'。這在最一般的情況下也能正常工作。 – mat

+1

實例化錯誤並不一定是壞事:在@ CapelliC的答案中,他們保護if-then-else不會產生不完整的答案。但是,一旦你上面簡單的算術,你就不能再使用原始的if-then-else。有關更多信息,請參閱[this](http://stackoverflow.com/a/37057721/772868)。 – false

+1

如果你真的堅持使用if-then-else,而不是寫:'max(A,B,C): - if_(A#> B,C#= A,C#= B)。 A,B,真): - A#> B.#>(A,B,false): - A#= false