3

最も右側の出現を維持しながら、リストから重複を削除しようとしています。例:これ[1,2,3,1,2][3,1,2] Prolog での最初の試行の 1 つであり、何が間違っているのかわかりません。常に false を返します。これは私のコードです:

%nrap(L:list,E:element,S:integer)
%L - the initial list, list of integers
%E - the element, integer
%S - the result, nrap of E in L, S integer
%flow model: (i,i,o),(i,i,i)

nrap([],_,0).
nrap([H|T],E,S):-
    H=E,
    nrap(T,E,S1),
    S is S1+1.
nrap([H|T],E,S):-
    H\=E,
    nrap(T,E,S).

%transform(L:list,L2:list,R:list)
%L - the initial list, list of integers
%L2 - copy of the initial list
%R - the resulted list, without duplicates, list of integers
%flow model: (i,i,o),(i,i,i)

transform([],[],[]).
transform([H|T],L2,[H|R]):-
    nrap(L2,H,S),
    S=1,
    transform(T,L2,R).
transform([H|T],L2,R):-
    nrap(L2,H,S),
    S>1,
    transform(T,L2,R).
4

3 に答える 3

3

私は純粋でしょうか、それとも不純でしょうか? 簡単に保存できるのであれば、 なぜを犠牲にすることを考える必要があるのでしょう! andを
使用して、とそのの「ツイン」を定義します。memberd_t/3if_/3list_rset/2list_lset/2

list_ r set([], [])。%右端のオカレンスを保持
list_rset([E|Es], Rs0) :-
   if_(memberd_t(E, Es),
       Rs0 = Rs、
       Rs0 = [E|Rs])、
   list_rset(Es, Rs).

list_ l set([], [])。%最左のオカレンスを保持
list_lset([E|Es], Ls) :-
   post_pre_lset(Es, [E], Ls). % は内部補助述語を使用します

post_pre_lset([], _, [])。            
post_pre_lset([E|Es], Pre, Ls0) :- % 2 番目の引数: 後読みアキュムレータ
   if_(memberd_t(E, Pre),
       Ls0 = Ls、
       Ls0 = [E|Ls])、
   post_pre_lset(Es, [E|Pre], Ls).

クエリを実行してみましょう。

?- _Es = [1,2,3,1,2], list_lset(_Es, Ls), list_rset(_Es, Rs).
Ls = [1,2,3]、Rs = [3,1,2]。% は決定論的に成功します

上記のクエリでは、リストの先頭末尾の両方で1先行します。が最初に先行し、最後に続く場合 (例: ) ?2[1,2,3,1,2]
12[1,2,3,2,1]

?- _Es = [1,2,3,2,1], list_lset(_Es, Ls), list_rset(_Es, Rs).
Ls = [1,2,3]、Rs = [3,2,1]。% は決定論的に成功します

list_rset/2次に、変数のみを含むリストを使用する、より一般的な目標を見ていきます。
@PauloMoura の提案に感謝します!

?- Es = [A,B,C,A,B], list_rset(Es,Rs).
   Es = [C,C,C,C,C], Rs = [ C], A=B , B=C
; Es = [B,B,C,B,B], Rs = [C, B], A=B , dif(B,C)
; Es = [C,B,C,C,B], Rs = [ C,B], A=C , dif(B,C)
; Es = [A,C,C,A,C]、Rs = [A,C]、dif(A,C)、B=C
; Es = [A、B、C、A、B]、Rs = [C、A、B]、dif(A、B)、dif(A、C)、dif(B、C)。

残りの目標 (上記) はどうなっていますか? 十分なインスタンス化がなければ、dif/2決定できません。
論理的な健全性を維持するために、制約の実行が遅延されます。

Xs最後に、もう 1 つの使用例:変数基本用語の両方を持つ「入力」リスト。

?- Es = [A,B,z], list_rset(Es,Rs).
   Es = [z,z,z], Rs = [ z], A=B , B=z
; Es = [B,B,z], Rs = [B, z], A=B , dif(B,z)
; Es = [z,B,z], Rs = [ B,z], A=z , dif(B,z)
; Es = [A,z,z], Rs = [A, z], dif(A,z), B=z
; Es = [A,B,z]、Rs = [A,B,z]、dif(A,B)、dif(A,z)、dif(B,z)。
于 2015-10-21T20:23:45.923 に答える
1

これはこの以前の回答のフォローアップです...この回答ではを使用しています!

私たちはand —のdcg類似物にlset//1基づいて構築し:memberd_t/3if_//3if_/3

lset([]) -->
   []。
lset([X|Xs]) -->
   [バツ]、
   lset_pre(Xs,[X])。

lset_pre([],_) -->
   []。
lset_pre([X|Xs],Pre) -->
   if_ ( memberd_t (X,Pre), [], [X]),
   lset_pre(Xs,[X|Pre])。

についても同じrset//1:

rset([]) -->
   []。
rset([X|Xs]) -->
   if_ ( memberd_t (X,Xs), [], [X]),
   rset(Xs)。

いくつかのサンプル クエリ:

?- _Es = [1,2,3,1,2], phrase(lset(_Es),Ls), phrase(rset(_Es),Rs).
Ls = [1,2,3], Rs = [3,1,2].               % succeeds deterministically

?- _Es = [1,2,3,2,1], phrase(lset(_Es),Ls), phrase(rset(_Es),Rs).
Ls = [1,2,3], Rs = [3,2,1].               % succeeds deterministically
于 2015-10-23T12:42:37.763 に答える
0

これはあなたが作っているよりも簡単です。「セット」内の要素は最後に出現した順序である必要があるため、リストのコピーを保持する必要はまったくありません。リストの残りの部分 (テール) と比較するだけです。

最初のリストが常にグラウンドになることがわかっている場合 (たとえば、すべての要素が整数である場合)、次のように書くことができます。

list_set([], []).
list_set([X|Xs], Ys0) :-
    (   memberchk(X, Xs)
    ->  Ys0 = Ys
    ;   Ys0 = [X|Ys]
    ),
    list_set(Xs, Ys).

memberchk/2基底項が基底項のリストにあるかどうかを確認するために使用できます。一度だけ成功または失敗します。

より一般的な解決策は、要素がそれに続くすべての要素と異なる場合は要素がセットに含まれ、そうでない場合は削除されるという制約を課すことです。

list_set([], []).
list_set([X|Xs], [X|Ys]) :-
    maplist(dif(X), Xs),
    list_set(Xs, Ys).
list_set([X|Xs], Ys) :-
    \+ maplist(dif(X), Xs),
    list_set(Xs, Ys).

ここでは、次のmaplist(dif(X), Xs)ことを意味します。

XXsリスト(末尾)のすべての要素とは異なります。

そして\+ Goal成功し、その後成功Goalしません。

この定義では:

?- list_set([1,2,3,1,2], S).
S = [3, 1, 2] ;
false.

?- list_set([1,2,3,3,1,1,2], S).
S = [3, 1, 2] ;
false.

?- list_set([A,B,C,A,B],Xs).
Xs = [C, A, B],
dif(A, B),
dif(C, B),
dif(C, A) ;
false.
于 2015-10-21T19:03:02.707 に答える