2017-02-23 71 views
0

我對prolog有些新鮮,我試圖弄清楚如何在訂單無關緊要時實現綁定列表元素。我在代碼的最後兩行證明了這一點。這樣做似乎微不足道,但它沒有約束力。在序言中綁定無序列表

fh(Hand) :- 
    is_card(R, _, C1), 
    is_card(R, _, C2), 
    is_card(R, _, C3), 
    C1 \== C2, 
    C2 \== C3, 
    C1 \== C3, 

    is_card(RR, _, D1), 
    is_card(RR, _, D2), 
    R \= RR, 
    D1 \== D2, 
    is_set(Hand), 
    list_to_set([C1,C2,C3,D1,D2], Hand). 

我將不勝感激一些提示。 (謂語名稱和功能隱蔽,防止抄襲)

+0

您是否使用庫(列表)中的is_set和list_to_set?也許list_to_set需要一些順序,它說:「當Set與List具有相同的順序時,它是True。」我不知道如何運行你的代碼,所以我不知道。 – 2017-02-23 08:55:40

+0

這是真的,顯然它只是一個元素不重複的意義上的集合。 – lamino

回答

0

您可以構建具有更嚴格的條件,你的手來下訂單方式,而不是隻檢查它們是不同的,建立獨特的元素:

fh(Hand) :- 
    is_card(R, _, C1), 
    is_card(R, _, C2), 
    is_card(R, _, C3), 
    C1 @< C2, 
    C2 @< C3, 

    is_card(RR, _, D1), 
    is_card(RR, _, D2), 
    dif(R, RR), 
    D1 @< D2. 

這樣,你使用排序來構建你的卡手,這樣你就沒有任何重複。既然你不關心訂單是什麼,有一個特定的訂單不會影響需求,並提供一種方法來確定唯一性。

+0

我沒有使用數字。有沒有辦法爲一個化合物(卡)定義'@<'? – lamino

+1

@lamino'@<'適用於任何形式的術語。例如'a @ lurker

+1

@lamino你需要澄清你原來的問題。您錯過了很多關於您的要求的細節。如果'is_card/3'在你的事實數據庫中,結果中不應該有任何變量。所以一個例子會非常有幫助。顯示事實的樣子。或者,如果'is_card/3'是謂詞,則顯示謂詞。 – lurker

0

讀庫(列表)提供的資料,看來您的使用情況下,它可能是最好的代表一組作爲排序列表沒有重複,與sort/2製成。

這裏是我所得到的:

?- A = [2,3,1], 
    B = [1,1,2,3,2,3], 
    sort(A, S), 
    sort(B, S). 
A = [2, 3, 1], 
B = [1, 1, 2, 3, 2, 3], 
S = [1, 2, 3]. 

sort(A, S)將確保S是使用相同的元素作爲一個有序列表,並sort(B, S)將確保如果你讓一組的B是的與A相同。

我看到is_set/1的執行可能與length(Set, Lenght), sort(Set, Sorted), length(Sorted, Len).相同,但我找不到'$skip_list'的定義。但我看到:

?- '$skip_list'(Len, [2,3,1], Tail). 
Len = 3, 
Tail = []. 
+0

'is_set(X): - sort(X,X).'足夠了 – CapelliC

+0

@CapelliC我認爲足夠的,如果X已經是一個排序集合,我認爲問題是[2,3,1]也應該是「設置爲「 – 2017-02-24 11:29:30

+0

is_set/1沒有錯誤條件,沒有實例化它的參數,並且如果元素不是按照標準順序,則確實成功。修正''det'到'semidet' –

0

像其他評論者,我假設你正在使用is_set/1從SWI-Prolog的圖書館。在您的代碼中,您有一個電話

is_set(Hand) 

其中Hand是一個自由變量。你的目標似乎是以此作爲一種發電機或「類型聲明」的,但是,這並不工作:

?- is_set(X). 
false. 

documentation of is_set/1部分內容如下:

is_set(@set) [det]

如果Set是沒有重複的正確列表,則爲真。

這裏有一些事情正在進行。據SWI's mode documentationdet意味着「則成功恰好一次沒有選擇點」,並@意味着「之爭將不會再實例化比它在呼叫時間。」這些把兩者一起,is_set/1不能是一臺發電機,因爲它不枚舉的解決方案:它沒有實例化它的參數,甚至一個單一的解決方案(@),即使它沒有,它會不會成功不止一次( det)。 (事實上​​,det謂語應該永遠不會失敗,但is_set/1確實,這似乎是一個文檔錯誤,正確的註釋爲semidet

所以:你不能使用is_set/1作爲發電機,只能作爲一個類型檢查。但是,即使作爲一種檢查,因爲自由變量肯定是「正確的名單」它不能幫助你在這裏。但是,這裏不需要生成器或類型檢查。除去is_set/1電話,list_to_set/2單獨應該做你想做的。