从列表中删除重复的元素

时间:2014-06-14 21:29:41

标签: prolog

这是我的代码

removevowels(L1, L2) :-
   removevowels(L1, L2, []).

removevowels([], [], _).
removevowels([X|L1], [X|L2], Aux) :-
   consonant(X), 
   not(member(X, Aux)), 
   removevowels(L1, L2, [X|Aux]).
removevowels([X|L1], L2, Aux) :-
   not(consonant(X)), 
   removevowels(L1, L2, Aux).

如果我这样做:

?- removevowels([a,m,m,n], X).

应打印

X = [m, n]

但它给出了假,如果我运行这个

?- removevowels([a,m,n], X).
X = [m,n]

没有重复元素时没关系。

使用了一些熟悉的谓词:

member(X, [X|_]).      
member(X, [_|Tail]) :-   
   member(X, Tail). 

consonant(b)
consonant(c), etcetc ....

我的代码出了什么问题?

2 个答案:

答案 0 :(得分:2)

最好先用ISO not/1替换(\+)/1

对于调试,您要做的第一件事就是最小化问题。例如,查询

?- removevowels([m,m],X).

同样糟糕。但要小得多。那么你的辅音规则是什么?有一个单一规则

removevowels([X|L1], [X|L2], Aux) :-
   consonant(X),
   \+member(X, Aux), 
   removevowels(L1, L2, [X|Aux]).

所以辅音只有只出现一次,下一次出现会导致失败。

如果您仍然不确定查询失败的原因,您可能还需要概括查询。而不是看到removevowels([m,m],X)失败,你可能会问

?- removevowels([m,Y],X).

表示:是否有任何 Y,以便有解决方案。但是,如果您的程序是"关系",则此方法才有效。在你的情况下,最后一条规则阻止了这个:

removevowels([X|L1], L2, Aux) :-
   \+consonant(X), 
   removevowels(L1, L2, Aux).

X作为未实例化的变量永远不会成功。我宁愿使用:

removevowels([X|L1], L2, Aux) :-
   vowel(X), 
   removevowels(L1, L2, Aux).

回到辅音: 您缺少的是对已经存在的辅音的单独规则,或者某些"默认"如果 - 则 - 否则。

此外,这种额外检查可能不是处理此问题的最有效方法。也许只是先提取元音,然后再sort/2

答案 1 :(得分:0)

在第二个子句中,连接中有两个条件,而最后一个子句只有一个。我会用一个cut来提交好的情况,让最后一个句子只作为一个可信的跳过子句:

removevowels([], [], _).
removevowels([X|L1], [X|L2], Aux) :-
   consonant(X), 
   not(member(X, Aux)), 
   !, removevowels(L1, L2, [X|Aux]).
removevowels([_X|L1], L2, Aux) :-
   removevowels(L1, L2, Aux).

使用if / then / else构造最后2个子句,我们避免了false指出的问题:

removevowels([], [], _).
removevowels([X|L1], R, Aux) :-
    (   consonant(X), 
        not(member(X, Aux))
    ->  R=[X|L2],
        removevowels(L1, L2, [X|Aux])
    ;   removevowels(L1, R, Aux)
    ).
相关问题