Recursion Prolog程序中的结果无效

Recursion Prolog程序中的结果无效,recursion,prolog,Recursion,Prolog,我的程序旨在消除列表中的重复元素。我认为这是正确的。 我试着让它工作,把削减,但它没有给出正确的结果 member(X,[X|_]). % If X is Head, it is a member member(X,[_|T]) :- member(X,T). % If not, Recursively check the tail. remove_duplicates([],[]). remove_duplicates([H|T],R):-member(H,T),remove_duplica

我的程序旨在消除列表中的重复元素。我认为这是正确的。 我试着让它工作,把削减,但它没有给出正确的结果

member(X,[X|_]). % If X is Head, it is a member
member(X,[_|T]) :- member(X,T). % If not, Recursively check the tail.

remove_duplicates([],[]).
remove_duplicates([H|T],R):-member(H,T),remove_duplicates(T,R).
remove_duplicates([H|T],[R|REM]):-remove_duplicates(T,REM).
然而,我得到的结果是:
I=[\u G2608、\u G2611、\u G2614、\u G2615]

对于输入
删除重复项([a,b,a,b,b,c],I)

都铎的解决方案很好。然而,我已经看到了在适当的情况下使用条件语句的好处,尽管我发现美学方面有点欠缺,因此我建议使用以下解决方案:

remove_duplicates([], []).
remove_duplicates([H|T], R) :-
  (   memberchk(H,T)
  ->  remove_duplicates(T, R)
  ;   remove_duplicates(T, R0), 
      R = [H|R0]
  ).
这样的显式条件不会创建虚假的选择点。正是这个选择点导致了都铎的解决方案需要一个否定的
成员/2
,而你正试图用一个剪切来纠正这个问题。因此,尽管它看起来不那么漂亮,但它是一个更有效的解决方案

另外,在不需要
member/2
生成解决方案的情况下,使用
memberchk/2
而不是
member/2
是一种小型优化。比较:

?- time(remove_duplicates([a,b,a,b,b,c], I)).
% 14 inferences, 0.000 CPU in 0.000 seconds (96% CPU, 1037114 Lips)
I = [a, b, c].
要查看都铎对代码的修订:

?- time(remove_duplicates([a,b,a,b,b,c], I)).
% 28 inferences, 0.000 CPU in 0.000 seconds (94% CPU, 2264822 Lips)
I = [a, b, c] ;
% 28 inferences, 0.000 CPU in 0.000 seconds (92% CPU, 1338752 Lips)
I = [a, b, c] ;
% 15 inferences, 0.000 CPU in 0.000 seconds (88% CPU, 1065341 Lips)
false.

这是一个既纯粹又高效的版本,因为它只需要恒定的辅助空间。到目前为止发布的解决方案在最坏的情况下需要与第一个参数中列表大小成比例的空间。但现在谈谈正确性:

?- remove_duplicates([A,B], Fs).
在此,我们要问:

A
B
的外观如何才能生成一个没有重复项的列表
Fs

这个问题不能简单地通过说明具体的
Fs
来回答,因为这个
Fs
可能是
[A,B]
或者
[A]
应该
A
B
相同

?- remove_duplicates([A,B],F).
   A = B,
   F = [B]
;  F = [A, B],
   dif(A, B).
这里有一个解决方案。此定义需要中定义的单调
if\uu/3
memberd\u truth/3


就个人而言,我更喜欢一个关系更密切的名称,比如
list\u unique/2
list\u nub/2

最后一条规则应该是:
删除重复项([H | T],[H | REM]):-\+成员(H,T),删除重复项(T,REM如果你不坚持保持每个元素第一次出现的原始顺序,只是
sort/2
您的原始列表我怀疑您在第3个
remove_duplicates/2
子句上看到了一个单例警告,原因是“orphan”
R
变量。比我聪明的人说过,剪切永远不能使错误的程序正确。在几种情况下使用序言“if else”之后,它开始在美学上(有点)对我产生影响
remove_duplicates([], []).
remove_duplicates([E|Es], Fs0) :-
   if_( memberd_truth(E, Es) , Fs0 = Fs , Fs0 = [E|Fs] ),
   remove_duplicates(Es, Fs).