1

次のクエリ (および以下で定義されている述語) に対して、予期しない答えが得られます。

?- rep([1,2,3], 3, [2,3,4], L).
L = [1, 2, 2, 3, 4] ;
L = [1, 2, 3].                           % unexpected answer

最初の結果は私が望むものです。欲しくない2枚目…

2回目はどうすれば防げますか?おそらく!どこかに追加することによって?

concat([], L, L).
concat([H|T], L, [H|Res]) :-
   concat(T, L, Res).

repl([], _, _, []).
repl([Val|T], Val, Repl, Res) :-
   repl(T, Val, Repl, Temp),
   concat(Repl, Temp, Res).
repl([H|T], Val, Repl, [H|Res]) :-
   repl(T, Val, Repl, Res).
4

3 に答える 3

3

リストごとに複数の一致を許可するには、 maplist/3を使用して次のように進めます。

item_replacement_item_mapped(E、E、E、E)。
item_replacement_item_mapped(X, _, E, [E]) :-
   差分(X, E)。

repl(Es0、X、Xs、Es) :-
   maplist (item_replacement_item_mapped(X,Xs), Es0, Ess1),
    append (Ess1, Es)。

サンプルクエリ:

?- repl([1,2,3], 3, [2,3,4], L).
   L = [1,2,2,3,4]
;  false.

?- repl([x,y,x,y,x], x, [x,y,x], L).
   L = [x,y,x,y,x,y,x,y,x,y,x]
;  false.
于 2015-12-22T11:54:01.647 に答える
2

@repeat がすでにうまく示しているように、制約dif/2を使用して 2 つの用語が異なることを説明する必要があります。これにより、予期しない間違った 2 番目のソリューションを回避できます。

さらに、リストを記述するときはいつものように、表記の使用も検討してください。非終端記号list//1do を使用して、特定の位置で他のリストに簡単かつ効率的に接合できるようにリストを宣言的に記述することができます。

検討:

replacement([], _, _) --> [].
replacement([L|Ls], L, Rs) -->
    list(Rs),
    replacement(Ls, L, Rs).
replacement([L|Ls], R, Rs) --> [L],
    { dif(L, R) },
    replacement(Ls, R, Rs).

list([]) --> [].
list([L|Ls]) --> [L], list(Ls).

phrase/2DCG を使用するには、interface 述語を使用します。例えば:

?- phrase(replacement([1,2,3], 3, [2,3,4]), Ls).
Ls = [1, 2, 2, 3, 4] ;
false.

あらゆる方向に作用する真の関係です。次のような非常に一般的な質問に答えることができます:どの項目が別のリストに置き換えられましたか? 例:

?- 句(置換([1,2,3], E, [2,3,4]), [1,2,2,3,4])。
E = 3 ;
間違い。
于 2015-12-22T13:19:13.137 に答える
0

編集

これは毛むくじゃらになっており、私の答えはリクエストを正確に説明していませんでした...最小限の変更でコードを見てみましょう:

concat([], L, L).
concat([H|T], L, [H|Res]) :-
   concat(T, L, Res).

repl([], _, _, []).
repl([Val|T], Val, Repl, Res) :- !, % as noted by @repeat, better to commit early...
   repl(T, Val, Repl, Temp),
   concat(Repl, Temp, Res). % !.
repl([H|T], Val, Repl, [H|Res]) :-
   repl(T, Val, Repl, Res).

カットは単に2番目の句をコミットします...

古い回答を再開する

concat/3 はよく知られている append/3 と同じなので、このアプローチを検討してください

repl(ListOrig, Element, Replace, ListUpdated) :-
      append(H, [Element|T], ListOrig),
      append(H, Replace, Temp),
      append(Temp, T, ListUpdated).

?- repl([1, 2, 3], 3, [2, 3, 4], L).
L = [1, 2, 2, 3, 4] ;
false.

編集

コメントで要求されているように、この拡張機能は、単純なパターン マッチングを使用して、変更に一致する要素のリストを処理します (注: 前の句の前に追加します)。

repl(ListOrig, [], _Replace, ListOrig).
repl(ListOrig, [E|Es], Replace, ListUpdated) :-
    repl(ListOrig, E, Replace, Temp),
    repl(Temp, Es, Replace, ListUpdated).

テスト

?- repl([1,2,3],[2,3],[x,y,z],R).
R = [1, x, y, z, x, y, z] ;
false.

編集

Element が見つからなくても失敗しないことに気づきませんでした...最後の「catchall」句でこのケースを処理できます。

repl(ListOrig, _Element, _Replace, ListOrig).

またはそれ以上に、元のように拡張します

repl(ListOrig, Element, Replace, ListUpdated) :-
      (  append(H, [Element|T], ListOrig)
      -> append(H, Replace, Temp),
         append(Temp, T, ListUpdated)
      ;  ListOrig = ListUpdated
      ).
于 2015-12-22T10:45:16.163 に答える