2016-07-28 230 views
1

我是新來的Prolog和我有麻煩搞清楚如何找到包含數字和字母列表中的第二個最低尋找第二最小值。當它包含一個字母時,它應該顯示一個錯誤,當它有一個數字時,它應該顯示一個錯誤。到目前爲止,我有這個,但我不知道如何開始我的編碼具有信件...SWI-Prolog的:在列表中

secondMin([_]) :- 
    print("ERROR: List has fewer than two unique elements."), 
    !. 
secondMin(List, M2) :- 
    min_list(List, M1), 
    delete(List, M1, List1), 
    min_list(List1, M2). 

輸出應該是這樣的:

?- secondMin([17,29,11,62,37,53], M2). 
M2 = 17 
?- secondMin([512], M2). 
ERROR: List has fewer than two unique elements. 
?- secondMin([7,5.2,3,6,-3.6,9,-2], M2). 
M2 = -2 
?- secondMin([12,2,b,7], M2). 
ERROR: "b" is not a number. 
?- secondMin([3,3,3], M2). 
ERROR: List has fewer than two unique elements. 
+0

如果它所具有既不是一個整數,也不是字母元素?例如'abc'或'1.23'? – lurker

+0

對不起,我不是故意說整數只是任何唯一的數字 – tadashi

+2

「第二最小」聽起來很好定義。然而,secondMin([1,1,2,3],M)'現在是'M = 1'還是'M = 2'? – false

回答

0

最簡單的,而且是必須的,方法是使用maplist來確定是否有任何非數字。然後使用sort獲得獨特的第二分鐘。

secondMin(L, M) :- 
    ( maplist(number, L) 
    -> ( sort(L, [_,Second|_]) 
     -> M = Second 
     ; print("List has fewer than two unique elements.") 
     ) 
    ; print("List has non-numeric elements") 
    ). 


作爲@Repeat指出在他的評論,上述方案是在這個意義上「天真」,雖然它產生了一個有效輸入一個正確的結果,它沒有相應的錯誤處理除了顯示診斷消息,但然後成功。

這裏有一個更徹底的執行,當預期沒有定義的第一個參數上異常引發:

secondMin(L, M) :- 
    ( ground(L) 
    -> ( is_list(L), 
      maplist(number, L) 
     -> ( sort(L, [_,Second|_]) 
      -> M = Second 
      ; throw('List has fewer than two unique elements') 
      ) 
     ; throw('First argument is not a list of numbers') 
     ) 
    ; throw(error(instantiation_error, _)) 
    ). 
+0

你的答案(這在錯誤的情況下打印出「ERROR」和*然後成功*)是**路*​​關閉!而不是使用例外! IIRC你的主要Prolog處理器是GNU Prolog ...所以請閱讀http://www.gprolog.org/manual/gprolog.html#sec32並重新提供/改進你的答案。我知道使用例外有點令人厭煩,但要走高速公路。 – repeat

+0

你可能要開始像'(接地(L) - > ...;擲(誤差(instantiation_error,_)))'如果你想在代碼中使用'排序/ 2' ... – repeat

+0

另一個事情......應該推遲「排序/ 2」目標中的隱含統一,以避免問題的嚴重性。爲什麼不這樣做:'(sort(L,[_,Second | _]) - > M = Second; throw(...))' – repeat