列表替换中的Prolog元素

Don*_*ald 6 replace list prolog

嗨,我想知道你是否可以帮我解决这个问题

从Prolog编程:编写Prolog脚本,用另一个给定元素替换列表中的任何给定元素.例如:

replace( 3, a,[1,2,3,4,3,5], [1,2,a,4,a,5])=true
Run Code Online (Sandbox Code Playgroud)

提前谢谢了

svi*_*ick 12

在Prolog中,大多数列表处理是通过处理头部然后递归处理列表的其余部分来完成的.当然,你不能忘记基本情况,这是一个空列表.

用空列表中的任何内容替换任何内容都会再次出现在空列表中.如果列表的头部与要替换的元素相同,则替换它,否则,保持原样.在这两种情况下,递归处理列表的其余部分.从英语翻译成Prolog:

replace(_, _, [], []).
replace(O, R, [O|T], [R|T2]) :- replace(O, R, T, T2).
replace(O, R, [H|T], [H|T2]) :- H \= O, replace(O, R, T, T2).
Run Code Online (Sandbox Code Playgroud)


rep*_*eat 6

到目前为止,在其他答案中呈现的所有实现在与非基础术语一起使用时在逻辑上是不合理的.考虑原始查询和一个轻微的变体:

?- replace(3,three,[1,2,3],Xs).
Xs = [1,2,three] ;                 % OK: correct
false

?- A=3, replace(A,B,[1,2,3],Xs).   % OK: correct
Xs = [1,2,B], A = 3 ;
false
Run Code Online (Sandbox Code Playgroud)

有用!让我们问一些非常相似的问题:

?- replace(A,B,[1,2,3],Xs).        % FAIL: should succeed more than once...
Xs = [B,2,3], A = 1 ;              %       ... but the other solutions are missing 
false

?- replace(A,B,[1,2,3],Xs), A=3.   % FAIL: this query _should_ succeed ...
false                              %       ... it does not!
Run Code Online (Sandbox Code Playgroud)

这是怎么回事?元逻辑内建 (!)/0(\=)/2,这是非常困难的使用权,并经常使代码脆,不纯,并且在逻辑上站不住脚.

为了保持逻辑的健全性,坚持逻辑纯洁,尽可能避免使用元逻辑"功能"!幸运的是,大多数Prolog实现支持dif/2作为逻辑替代(\=)/2.我们来使用它:

% code by @svick, modified to use dif/2 instead of (\=)/2
replaceP(_, _, [], []).
replaceP(O, R, [O|T], [R|T2]) :- replaceP(O, R, T, T2).
replaceP(O, R, [H|T], [H|T2]) :- dif(H,O), replaceP(O, R, T, T2).
Run Code Online (Sandbox Code Playgroud)

让我们再次运行上面的查询,这次改进了replaceP/4:

?- replaceP(3,three,[1,2,3],Xs).
Xs = [1,2,three] ;                 % OK: correct, like before
false

?- replaceP(A,B,[1,2,3],Xs).       % OK: four solutions, not just one
Xs = [B,2,3], A = 1 ;         
Xs = [1,B,3], A = 2 ;
Xs = [1,2,B], A = 3 ;
Xs = [1,2,3], dif(A,1),dif(A,2),dif(A,3) ;
false

?- replaceP(A,B,[1,2,3],Xs), A=3.  % OK (succeeds now)
Xs = [1,2,B], A = 3 ;                 
false
?- A=3, replaceP(A,B,[1,2,3],Xs).  % OK (same as before)
Xs = [1,2,B], A = 3 ;
false
Run Code Online (Sandbox Code Playgroud)