在嵌套列表中替换(prolog)

时间:2009-11-20 15:03:30

标签: prolog

/ *替换(X,Y,Xs,Ys)如果列表Ys是将Y替换为列表X中所有出现的X的结果,则为真。

这是我到目前为止所做的:

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]] .

我应该在这个程序中添加什么?

2 个答案:

答案 0 :(得分: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)
    ).

答案 1 :(得分:1)

问题是,一旦找到嵌套列表,就会忘记嵌套列表中背后的。相反,在使用嵌套嵌套进行递归之后,只需像以前一样继续。因此,您应该更改最后一个子句如下:

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

除了之外,还有几种方法可以改进代码:

  1. 使用cuts!/0)停止回溯。通过这种方式,您不必重复自己。
  2. 您可以使用is_list/1来测试参数是否为列表。
  3. 可以使用更多空格。真。
  4. 所以,另一种解决方案是(现在使用\+/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]].