【问题标题】:replacing terms in a list prolog替换列表序言中的术语
【发布时间】:2012-04-16 08:34:34
【问题描述】:

我正在尝试编写一个 prolog 程序,它将一个列表、一个 old_subterm 和一个 new_subterm 作为输入,并返回一个新列表,其中 old_subterm 的每个实例都已替换为 new_subterm。 比如

| ?- sub_rep([h(A,g(x)),g(x),g(3)],g(x),p,T).
T = [h(A,p),p,g(3)] ? ;
no

所以我可以使用以下代码使其与基本列表一起使用:

replace(E,S,[],[]).
replace(E,S,[E|T1],[S|T2]):-
    replace(E,S,T1,T2).
replace(E,S,[H|T1],[H|T2]):-
    E\=H, 
    replace(E,S,T1,T2).

%(here's some example input/output)

?- replace(b,e,[a,b,c],L).
L = [a, e, c] ;
false.

?- replace(f(Y),g(Y),[f(Y),1,2,f(Y)],L).
L = [g(Y), 1, 2, g(Y)] ;
false.

但是当我尝试使用更复杂的列表时,例如

?- replace(g(Y),h,[f(g(Y)),g(Y),g(1)],L).

我得到以下答案:

Y = 1,
L = [f(g(1)), h, h] ;
false.

这不是我想要的,因为我希望它能够返回:

? - L = [f(h),h,g(1)] ;
false.

我是 prolog 的新手,我可能遗漏了一些明显的东西,但我不明白为什么在这种情况下变量 Y 会被实例化?在第二个示例中,这似乎不是问题。我想这与 g(1) 的外观有关,但我不明白为什么? 提前致谢! :)

【问题讨论】:

    标签: list replace prolog


    【解决方案1】:

    对您的问题的第一个观察:列表的长度相同!这听起来很适合maplist/3!

    replace(A, B, As, Bs) :-
       maplist(repl(A,B), As, Bs).
    

    问题的“递归”部分就这么多。现在,我们必须定义repl/4。 这是我对你想要什么的猜测:

    repl(A, B, A0, B0) :-
       ( A == A0 -> B = B0 ; A0 = B0 ).
    

    也许您想要一些其他测试来代替 (==)/2。

    【讨论】:

    • 啊!!我完全忘记了地图列表!非常感谢你提醒我! :) 希望它现在会(更顺畅)航行!
    • 好吧,我已经盯着这个看了一段时间,我还是有点撞墙了。为了确保我不感到困惑,我认为这类似于上面的代码的工作原理是否正确?我们使用 maplist/3 来应用“部分目标”repl。我们给 repl 我们想要替换的术语和我们想要替换它的术语,如果 A 恰好是列表中的那个术语,我们用 B 替换它,否则我们保留它。假设这是有点正确的,我遇到了嵌套化合物的问题,即我似乎无法替换 [s(f(a,b,g) 中的 ag(X) (X))]. 知道为什么吗?
    • 只替换列表中的元素,不替换子项。但是您在原始帖子中并没有要求这样做。
    • 啊,是的,我很抱歉!我也希望能够替换子项。我是否认为一种合理的解决方法是用另一个函数调用替换 repl/4 的 'A == A0' 部分,它首先检查 A == A0 是否,如果不是,则检查 A0 是否是一个化合物,如果是的话 =.. 它到一个列表并递归它?
    【解决方案2】:

    您应该“分解”您的术语以进行比较。

    replace(_, _, [], []).
    replace(E, S, [X|T1], [Y|T2]):-
        replace_term(E, S, X, Y),
        !, replace(E, S, T1, T2).
    replace(E,S, [H|T1], [H|T2]):-
        replace(E,S,T1,T2).
    
    replace_term(E, S, E, S) :- !.
    replace_term(E, S, T, R) :-
          T =.. [F|As],  % explode
          replace(E, S, As, Gs),
          R =.. [F|Gs].  % reassemble
    

    测试:

    ?- replace(a,b,[a(a),b,c],L).
    L = [a(b), b, c] ;
    false.
    
    
    ?- replace(g(y),h,[f(g(y)),g(y),g(1)],L).
    L = [f(h), h, g(1)] .
    

    当模式中有变量时,事情会变得更加复杂:

    ?- replace(g(Y),h,[f(g(Y)),g(Y),g(1)],L).
    Y = 1,
    L = [f(h), h, h] ;
    

    也许numbervars 可以提供帮助,或者我们必须设计一种策略来立即实例化变量...

    【讨论】:

    • 我可以看到这是一种更好的方法,但是我仍然遇到上面的错误,也就是说?- replace(g(Y),h,[f(g (Y)),g(Y),g(1)],L)。 Y = 1, L = [f(g(1)), h, h] ;错误的。关于为什么会发生这种情况的任何想法?再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 2017-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多