1

リストを、置き換える変数を含む別のリストに置き換えるにはどうすればよいですか。例えば

rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p]

xからzおよびzは、交換後も変更されません。

これまでのところ、リストのないものだけを実行しました

rep([], _, []).
rep(L1, H1=H2, L2) :-
   rep(L1, H1, H2, L2).

rep([],_,_,[]).
rep([H|T], X1, X2, [X2|L]) :-
   H=X1,
   rep(T,X1,X2,L),
   !.
rep([H|T],X1,X2,[H|L]) :-
   rep(T,X1,X2,L).
4

5 に答える 5

1

SWI-Prologを使用している場合、モジュールlambda.plがそこにあります:http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl次のように書くことができます:

:- use_module(library(lambda)).

rep(L, Rep, New_L) :-
    maplist(\X^Y^(member(X=Z, Rep)
              ->  Y = Z
              ;   Y = X), L, New_L).
于 2013-03-26T17:12:18.753 に答える
1

コードを可能な限り単純に保つようにしてください。

rep([], _, []).
rep([X|Xs], Vs, [Y|Ys]) :-
   ( memberchk(X=V, Vs) -> Y = V ; Y = X ),
   rep(Xs, Vs, Ys).

もちろん、変数値をチェックする慣用的な方法(memberchk / 2を介して)に注意してください。

さらにもっと慣用的な方法です。リストを変換することは、いくつかの言語の基本的な構成要素であり、Prologも例外ではありません。

rep(Xs, Vs, Ys) :- maplist(repv(Vs), Xs, Ys).
repv(Vs, X, Y) :- memberchk(X=V, Vs) -> Y = V ; Y = X .
于 2013-03-26T17:47:28.097 に答える
1

if_/3とを使用して続行する方法は次のとおりです(=)/3

Keyまず、ペアのリストからシングルを見つけようとしますK-V。追加の引数は、検索の成功を具体化します。

pairs_key_firstvalue_t([]       ,_  ,_    ,false).
pairs_key_firstvalue_t([K-V|KVs],Key,Value,Truth) :-
   if_(K=Key,
       (V=Value, Truth=true),
       pairs_key_firstvalue_t(KVs,Key,Value,Truth)).

次に、「見つからない」ケースを処理する必要があります。

assoc_key_mapped(Assoc,Key,Value) :-
   if_(pairs_key_firstvalue_t(Assoc,Key,Value),
       true,
       Key=Value).

を使用してすべてをまとめmaplist/3ます。

?- maplist(assoc_key_mapped([x-z,z-x,d-c]), [x,d,e,z,a,z,p], Rs).
Rs = [z,c,e,x,a,x,p].                       % OK, succeeds deterministically
于 2015-07-23T12:11:14.577 に答える
1

「再帰部分」をこの答えを改善しましょう。 find_first_in_t/4

:- meta_predicate find_first_in_t(2,?,?,?).
find_first_in_t(P_2,X,Xs,Truth) :-
   list_first_suchthat_t(Xs,X,P_2,Truth).

list_first_suchthat_t([]    ,_, _ ,false).
list_first_suchthat_t([E|Es],X,P_2,Truth) :-
   if_(call(P_2,E),
       (E=X,Truth=true),
       list_first_suchthat_t(Es,X,P_2,Truth)).

「欠けている部分」を埋めるために、次のように定義しますkey_pair_t/3

key_pair_t(Key,K-_,Truth) :-
   =(Key,K,Truth).

とに基づいてfind_first_in_t/4、次のようkey_pair_t/3に書くことができます。assoc_key_mapped/3

assoc_key_mapped(Assoc,Key,Value) :-
   if_(find_first_in_t(key_pair_t(Key),_-Value,Assoc),
       true,
       Key=Value).

それで、OPのユースケースはまだ機能しますか?

?- maplist(assoc_key_mapped([x-z,z-x,d-c]), [x,d,e,z,a,z,p], Rs).
Rs = [z,c,e,x,a,x,p].                            % OK. same result as before

上に構築find_first_in_t/4

memberd_t(X,Xs,Truth) :-                        % memberd_t/3
   find_first_in_t(=(X),_,Xs,Truth).

:- meta_predicate exists_in_t(2,?,?).           % exists_in_t/3
exists_in_t(P_2,Xs,Truth) :-
   find_first_in_t(P_2,_,Xs,Truth).
于 2015-07-23T14:07:09.423 に答える
0

あなたのコードはかなり混乱していると思います。一つには、とがrep/3ありrep/4ますが、変数バインディングのリストを渡す2番目の位置にリストがありません。H1=H2リストと一致する可能性はありませんrep/3。2番目の引数を調べるのはそれだけです。これがクラスの割り当てである場合は、少し遅れているようです。前の資料に少し時間をかけることをお勧めします。

解決策はあなたが思っているよりも簡単です:

rep([], _, []).
rep([X|Xs], Vars, [Y|Rest]) :-    member(X=Y, Vars), rep(Xs, Vars, Rest).
rep([X|Xs], Vars, [X|Rest]) :- \+ member(X=_, Vars), rep(Xs, Vars, Rest).

リスト内で「変数バインディング」を見つけるために使用member/2しています(これらはアトムであり、真のProlog変数ではないため引用符で囲んでいます)。リストに含まれている場合はYが置き換えられ、そうでない場合はXを使用し続けます。これにより望ましい効果が得られることがわかります。

?- rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p] ;
false.

これは、「または」を直接使用していくらか効率的にすることができます(そして選択ポイントを節約できます)。

rep([], _, []).
rep([X|Xs], Vars, [Y|Ys]) :- 
  (member(X=Y, Vars), ! ; X=Y), 
  rep(Xs, Vars, Ys).

見る:

?- rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p].
于 2013-03-26T14:46:32.193 に答える