2017-10-19 28 views
1

我試圖在Prolog中創建自己的排序規則,經過大量的試驗和錯誤之後,除了按下按鈕之外,我能夠使其工作。在swipl中,它會將我列表的最後一個值添加到列表中。爲什麼Prolog在分號後重複列表的最後一個值?

使用的代碼如下:

分鐘以列表找到的最小值,並返回它

min([H|[]],H). 
min([H|T],Min) :- 
    min(T,CurrentMin), 
    H < CurrentMin, 
    Min = H. 
min([H|T],Min) :- 
    min(T,CurrentMin), 
    CurrentMin =< H, 
    Min = CurrentMin. 

刪除發現你想在列表中刪除的元素,並返回與列表刪除元素

最後,sort_inc嘗試使用上述規則以增加順序創建排序列表。

sort_inc([H|[]],[H]). 
sort_inc(UnOrderedList,[H|OrderedTail]) :- 
    min(UnOrderedList,H), 
    remove(H,UnOrderedList,T), 
    sort_inc(T,OrderedTail). 

分選的偉大工程,但是當我按下swipl分號名單上運行的規則後,它會在列表中重複的最後一個值像這樣:

sort_inc([3,6,8,4],List). 
List = [3, 4, 6, 8] ; 
List = [3, 4, 6, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8, 8, 8, 8] ; 
List = [3, 4, 6, 8, 8, 8, 8, 8, 8|...] . 

爲什麼它重複這最後一個值,而不是在輸入分號時返回false?

回答

4

你在你的刪除/ 3的實施有問題,試試這個:

remove(X, [X|Rest], Result) :- 
    !, remove_sub(X, [X|Rest], Result). 
remove(X, [Y|Rest], Z) :- 
    X \= Y, 
    remove(X, Rest, RestRemoved), 
    Z = [Y|RestRemoved]. 
remove(_, [], []). 

remove_sub(X, [X|Rest], Rest). 
remove_sub(X, [Y|Rest], Z) :- 
    remove_sub(X, Rest, RestRemoved), 
    Z = [Y|RestRemoved]. 

確切的說,你的刪除/ 3的第一款留下列表完好,即使被刪除的元素產生不當的解決方案是其成員:

?- remove(1, [1, 2, 3], L). 
L = [2, 3] ; 
L = [1, 2, 3]. 

此外,請注意,該捆綁許多Prolog的實施方式將已刪除/ 3和最小/ 2實施方式中(以及排序,當然)。例如,束縛水飽和度,序言包括:

  • 刪除/ 3,它做幾乎你的你的刪除/ 3是應該做的,只是它刪除元素的所有實例一次
  • 選擇/ 3,這除了不允許刪除不在列表中的元素
  • min_list/2和min_member/2,找到列表的最小元素
  • sort/2, msort/2,predsort/3,做實際分類

即使您的目標是創建您的自定義實現,仍然值得使用它們來測試您自己的實現,例如您可以使用delete/3快速替換您的remove/3的調用,以找出問題出在哪裏。

+0

通過remove/3的第一個子句,你指的是remove(_,[],[])?我想這隻會返回一個空列表,如果有什麼試圖從空列表中刪除。我認爲如果元素不屬於,這將是一個很好的最後遞歸步驟。 –

+0

另外,在刪除規則中,刪除(1,[2],List)返回List = []。如果沒有正確的調用,我不希望單個元素列表丟失它的項目。 –

+1

看起來你是對的,我最初的remove/3的實現被打破了,對不起。這現在已經修復(希望),我已經更新了答案。此外,刪除/ 3我提到的也不同於我們的remove/3,因爲它刪除了所有出現的元素「瞬間」,而刪除/ 3在回溯期間逐個刪除它們。 –

相關問題