2011-11-08 70 views
1

我試圖找到列表的最小值(作爲學習體驗,因此沒有min)。獲取列表的最小值

我的做法是這樣的:

minimo([X], X). 
minimo([X,Y|Tail], N):- 
    (X > Y, minimo([Y,Tail], Y)); 
    (X <= Y, minimo([X,Tail], X)). 

這給了我下面的錯誤:

Syntax error: Operator expected

所以我的問題是:

  • 是什麼原因造成的語法錯誤?
  • 我會自己嘗試一次,如果它確實給出了正確的值,但是這實際上是否是一個正確的方法?

在此先感謝。

回答

4

有幾個錯誤在你的程序:

  1. 尖的由喬·萊曼出來,沒有'<='/2。它必須是'=<'/2

  2. ,當你調用minimo/2遞歸,您構建列表錯誤。而不是[Y,Tail]使用[Y|Tail]。否則,你會得到一個列表作爲第二個元素。

  3. 你的minimo/2遞歸調用的第二個參數綁定到YX。相反,它必須綁定到N。否則,你的N將永遠不會被實例化。

您可以通過添加割傷或使用IF-THEN-ELSE('->' + ;)進一步提高程序:

minimo([X], X) :- !. 
minimo([X,Y|Tail], N):- 
    (X > Y -> 
     minimo([Y|Tail], N) 
    ; 
     minimo([X|Tail], N) 
    ). 
3

語法錯誤是,因爲在Prolog中較小或相等= <,而不是< =。

我認爲這種方法可行,但你應該避免;在一個條款中。把它分成兩個子句。

此外,我認爲,你想要做的事就像|在遞歸[X尾]而不是[X,尾巴]

+0

'= <'似乎解決它,謝謝。但現在我得到了這個錯誤:'錯誤:>/2:算術:'[]/0'不是一個函數'',當我將它分成兩部分時,我得到:' - minimo([1,2, 3],X)。 錯誤:>/2:算術:\'[]/0'不是函數異常:(8)minimo([[3],[]],[3])?'謝謝! +1 – Trufa

2
min([H|T], Min) :- min(T, H, Min). 

min([], Min, Min). 
min([H|T], Min, Min1) :- 
    ( H < Min 
    -> min(T, H, Min1) 
    ; min(T, Min, Min1)). 
4

除其他版本的發佈已經,也考慮一個沒有if-then-else的版本,並且使用一個更具描述性的關係名稱(將列表與其最小值相關聯):

list_min([L|Ls], Min) :- list_min(Ls, L, Min). 

list_min([], Min, Min). 
list_min([L|Ls], Min0, Min) :- 
    Min1 is min(L, Min0), 
    list_min(Ls, Min1, Min). 

這種圖案被稱爲(從左邊起),我們可以將其等效地使用`與foldl/4寫:

list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min). 

min_(A, B, Min) :- Min is min(A, B). 

實施例的查詢:

?- list_min([1,0,2], Min). 
Min = 0. 

注雖然這不是一個真正的關係,並且由於使用低級算術,所以不能在所有方向上使用。例如,如果我們試圖在另一個方向上使用它,我們得到:

 
?- list_min([X,Y], 3). 
ERROR: is/2: Arguments are not sufficiently instantiated 

要使它成爲一個真正的解決方案,使用約束。例如,對於超過整數的解決方案:

:- use_module(library(clpfd)). 

list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min). 

min_(A, B, Min) :- Min #= min(A, B). 

這適用於所有方向:

?- list_min([X,Y], 3). 
X in 3..sup, 
3#=min(Y, X), 
Y in 3..sup.