2013-11-28 27 views
5

プロローグ内のリストから重複するエントリを削除しようとしています。リスト[a、b、a、c、b、a]は[a、b、c]を返します。私は組み込みの関数を使うことはできません。私はここで検索し、このコードを見つけました。プロローグ:重複の削除

member(X,[X|_]) :- !. 
member(X,[_|T]) :- member(X,T). 
set([],[]). 
set([H|T],[H|Out]) :- not(member(H,T)), set(T,Out). 
set([H|T],Out) :- member(H,T), set(T,Out). 

しかし、それは、[C、B、]ない私のリストを取得して返します[、bは、C]私は、要素とリストを取り、リストを返しますコードを削除してい

リスト内のその要素の出現が削除されます。だから私はそれを私の重複削除メソッドに組み込もうとしましたが、プロローグを理解できないのでうまく動作しません。論理的には、新しいリストの再帰呼び出しから頭のすべての出現を差し引いたリストを頭に入れたいと思う。これは、コードがsmlのように見えるでしょう。

fun remv(_,nil) = nil 
| remv(a,x::xs) = if x=a then remv(a,xs) else x::remv(a,xs); 
fun remvdub (nil) = nil 
| remvdub(x::xs) = x::remvdub(remv(x,xs)); 

だから、これは私が何をしないのですプロローグに

remv(_,[],[]). 
remv(X,[X|T],Ans) :- remv(X,T,Ans). 
remv(X,[H|T],[H|K]) :- remv(X,T,K). 

remvdub([],[]). 
remvdub([H|T],[H|Ans]) :- remvdub(Ans1,Ans), remv(H,T,Ans1). 

を試してみました何ですか?

答えて

7
% An empty list is a set. 
set([], []). 

% Put the head in the result, 
% remove all occurrences of the head from the tail, 
% make a set out of that. 
set([H|T], [H|T1]) :- 
    remv(H, T, T2), 
    set(T2, T1). 

% Removing anything from an empty list yields an empty list. 
remv(_, [], []). 

% If the head is the element we want to remove, 
% do not keep the head and 
% remove the element from the tail to get the new list. 
remv(X, [X|T], T1) :- remv(X, T, T1). 

% If the head is NOT the element we want to remove, 
% keep the head and 
% remove the element from the tail to get the new tail. 
remv(X, [H|T], [H|T1]) :- 
    X \= H, 
    remv(X, T, T1). 
+0

ありがとうSQBはまさに私がやろうとしていたことの論理です。あなたのコードを見ても、私が間違いを犯した場所を見つけることができないようで、私に同じことを読んでいます。しかし、あなたの作品はうまくいっています。 – user3043403

+0

ねえ、私はそれを考え出したと思います。 remvdub([H | T]、[H | Ans]):remvdub(Ans1、Ans)、remv(H、T、Ans1)。 remvdub([H | T]、[H | Ans]):remv(H、T、Ans1)、remvdub(Ans1、Ans)です。 – user3043403

2

投稿したPrologコードのスニペットは論理的に正しいです。

member(X,[X|_]) :- !. 
member(X,[_|T]) :- member(X,T). 
set(A,B) :- set(A, B, []). 
set([],[],_). 
set([H|T],[H|Out],Seen) :- not(member(H,Seen)), set(T,Out, [H|Seen]). 
set([H|T],Out, Seen) :- member(H,Seen), set(T,Out,Seen). 

アイデアは、のリストを表す三番目のパラメータを追加することです:あなたは、各重複項目の最後、コピーとは反対に、最初のを維持したい場合は、次のようにコードを変更することができます残りのリストとメンバーシップをチェックするのではなく、これまでに見たアイテムをチェックし、メンバーシップをチェックしてください。この3番目の引数を述語のユーザーから隠すために、set/2が追加されています。

Demo on ideone.

+0

働いたおかげでdasblinkenlight、!面白さから、コードの下のブロックで何をしようとしていたのですか?私はどこでヘッドを削除し、重複したヘッドを削除して、プログレッシブな小さなリストにプラグインするのですか? – user3043403

+0

@ user3043403私はsmlを理解していないので、動作するプロトタイプコードを理解できません。しかし、 'remvdub/2'述語の2番目の節は非常に疑わしく見えます。なぜなら、それは無限再帰に入っているように見えるからです。 – dasblinkenlight