2017-02-23 41 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单独应该做你想做的。