2015-11-26 181 views
1

我是新来的Prolog,我试图理解它。只填充一个列表,只发生多个列表元素

我开始用一些简单的程序,这应该:

  • 检查元素是否包含在列表的其余部分
    • 如果FALSE什么都不做
    • 如果真把它添加到第二个列表。 (只有一个字符应该添加到第二个列表中)。

与预期结果的一些例子:

?- occ([a,b,c,a,a,b,e,f,g], Y). 
Y = [a,b]. 

?- occ([a,a,a,a,a], Y). 
Y = [a]. 

?- occ([a,b,c,d,e,f,g], Y). 
Y = []. 

这是我写的代码,但我有一些问题(它总是返回true)。

occ([],[]). 
occ([],_Y). 
occ([X|Xs],[X|Y]) :- 
    occ(Xs,Y), 
    member(X,Xs), 
    not(member(X,Y)), 
    !. 
occ([_X|_Xs],_Y). 

我尝试使用调试器,我发现not(member(X,Y))总是false并在绑定区段只有XXs永不Y。任何意见非常感谢!谢谢。

UPDATE

我想我解决了这个问题,下面的代码:

occ([],[]). 
occ([X|Xs],[X|Y]) :- 
    occ(Xs,Y), 
    member(X,Xs), 
    not(member(X,Y)), 
    !. 
occ([_X|_Xs],[]). 

但我真的不知道为什么现在的工作......在3个occ我改变_Y[] .. 但为什么它会改变结果?

+1

你的谓词总是返回true,因为你有两个子句一起接受任何列表参数并成功。如果第一个参数是空列表'[]',则无论第二个参数是什么,'occ([],_Y).'总是会成功。如果第一个参数是至少一个元素的列表,并且不管第二个参数是什么,那么'occ([_ X | _Y],_Y).'将始终成功。你想要做的就是确保每个条款都是有意义的,只要表达一个关于它的论点的有效规则即可。 – lurker

+0

我试着更改我的代码,但是我无法实现我期待的内容......请你帮我多一点吗?我想我错过了一些东西。 – Marcx

+0

如果你用最新的变化来编辑你的问题,知道你现在的想法在哪里,它可能会有所帮助。 – lurker

回答

2

在这个答案中我们使用tpartition/4结合if_/3(=)/3

我们定义list_duplicateset/2这样的:

 
list_duplicateset([], []). 
list_duplicateset([E|Xs0], Ys0) :- 
    tpartition (= (E), Xs0, Es, Xs), 
    if_ (Es  = [], 
     Ys0 = Ys, 
     Ys0 = [E|Ys]), 
    list_duplicateset(Xs, Ys). 

首先,我们运行从this answer to a similar question抽取的样本查询:

?- list_duplicateset([1,2,2,3,4,5,7,6,7], Xs). 
Xs = [2,7]. 

接下来,让我们运行的OP给了疑问:

?- list_duplicateset([a,b,c,a,a,b,e,f,g], Xs). 
Xs = [a, b]. 

?- list_duplicateset([a,a,a,a,a], Xs). 
Xs = [a]. 

?- list_duplicateset([a,b,c,d,e,f,g], Xs). 
Xs = []. 

请注意,上面列出的所有查询都是 给出预期的答案,确定性地成功

相关问题