1

/* リスト Ys が、リスト Xs 内のすべての X の出現を Y に置換した結果である場合、substitute(X,Y,Xs,Ys) は真です。

これは私がこれまでに持っているものです:

subs(_,_,[],[]).
subs(X,Y,[X|L1],[Y|L2]):- subs(X,Y,L1,L2).
subs(X,Y,[H|L1],[H|L2]):- X\=H, not(H=[_|_]), subs(X,Y,L1,L2).
subs(X,Y,[H|_],[L2]):- X\=H, H=[_|_], subs(X,Y,H,L2).

私のコードは、ネストされたリストに続く要素を省略することを除いて機能します。例えば:

?- subs(a,b,[a,[a,c],a],Z).
Z = [b, [b, c]] .

このプログラムには何を追加すればよいですか?

4

2 に答える 2

2

(... -> ... ; ...) を使用して記述する方法は次のとおりです。

subs(_, _, [], []).
subs(X, Y, [H1|T1], [H2|T2]) :-
    (H1 == X ->
        H2 = Y
    ; is_list(H1) ->
        subs(X, Y, H1, H2),
        subs(X, Y, T1, T2)
    ;
        H1 = H2,
        subs(X, Y, T1, T2)
    ).
于 2009-11-20T20:25:44.117 に答える
1

問題は、ネストされたリストを見つけると、そのネストされたリストの背後にあるものを忘れてしまうことです。代わりに、ネストされたネストで再帰した後、以前と同じように続行します。したがって、最後の句を次のように変更する必要があります。

subs(X,Y,[H|L1],[H2|L2]):- X\=H, H=[_|_], subs(X,Y,H,H2), subs(X, Y, L1, L2).

それ以外にも、コードを改善する方法がいくつかあります。

  1. バックトラックを止めるには、カット( ) を使用します。!/0この方法では、自分自身を繰り返す必要はありません。
  2. is_list/1引数がリストかどうかをテストするために使用できます。
  3. より多くのスペースを使用しても問題ありません。本当。

したがって、代替ソリューションは次のとおりです(現在は\+/1代わりに使用していますnot/1):

subs(_, _, [], []).
subs(X, Y, [X|T1], [Y|T2]) :- subs(X, Y, T1, T2), !.
subs(X, Y, [H|T1], [H|T2]) :- \+ is_list(H), subs(X, Y, T1, T2), !.
subs(X, Y, [H1|T1], [H2|T2]) :- subs(X, Y, H1, H2), subs(X, Y, T1, T2).

デモンストレーション:

?- subs(a, b, [a, [a, [d, f, a]], a, b, a, [g]], Z).
Z = [b, [b, [d, f, b]], b, b, b, [g]].
于 2009-11-20T15:12:59.533 に答える