Prolog替代

时间:2013-03-26 14:33:05

标签: replace prolog substitution

如何将列表替换为包含要替换的变量的另一个列表。例如

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

6 个答案:

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

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

答案 2 :(得分: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

答案 3 :(得分:1)

通过移动"递归部分"来改进this answer。进入 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/4key_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).

答案 4 :(得分:0)

我觉得你的代码很混乱。首先,你有rep/3rep/4,但是没有一个在你传递变量绑定列表的第二个位置有一个列表。 H1=H2不能匹配列表,而且这是检查第二个参数的唯一rep/3子句。如果这是一个课堂作业,看起来你有点落后,我建议你花一些时间在之前的材料上。

解决方案比你想象的更简单:

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

答案 5 :(得分:0)

将连接词或谓词转换为真值函数的方法,即对于arity n的连接词或谓语词XX,尝试使用域中的最后一个参数来生成arity n + 1的谓词XX_t {true,false如果这种方法基于ISO标准,则存在严重的限制。

一个典型的限制是这些谓词不能轻易地删除(;)/ 2的分支。正常切割(!)也会影响(;)/ 2的周围,因为(;)/ 2被切割为透明。

需要的是局部剪切(sys_local_cut),它可以在本地影响剪切透明谓词。所以我猜这是所有这些看起来的盲点,看我有一个XX_t谓词,但它留给了许多选择点。

问题是局部剪切(sys_local_cut)不符合ISO标准。但我想如果XX_t connnectives的开发者会有这样的手段,它将达到与原始XX连接相同的选择点行为。

再见