您好,我想知道您是否可以帮我解决这个问题
从Prolog编程:编写Prolog脚本,用另一个给定元素替换列表中的任何给定元素。例如:
replace( 3, a,[1,2,3,4,3,5], [1,2,a,4,a,5])=true
非常感谢提前
答案 0 :(得分:11)
在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).
答案 1 :(得分: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
有效!让我们问一些非常相似的问题:
?- 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!
发生了什么?将责备放在元逻辑内置 (!)/0
和{{1}上},非常难以正确使用,并且经常使代码变得脆弱,不纯净,而且逻辑上不健全。
为了保持逻辑健全,坚持逻辑纯洁并弃用元逻辑"功能"只要有可能!幸运的是,大多数Prolog实现支持(\=)/2
作为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).
:
replaceP/4
答案 2 :(得分:0)
replace(_, _ , [], []).
replace(X, Y, [ X | Z ], [ Y | ZZ]):- ! , replace( X, Y, Z, ZZ).
replace(X, Y, [ W | Z], [ W | ZZ] :- replace(X, Y, Z, ZZ).
尽管如此,人们通常会安排3. arg成为第一个。严格来说,上面没有替换列表中的任何内容,只是第四个arg就像第三个中的那个,但是用Y'代替X'。
答案 3 :(得分:0)
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).
这个想法很简单,如果元素匹配,改变它,如果不匹配,则前进直到空。
答案 4 :(得分:0)
domains
I=integer*
K=integer*
Z=integer
A=integer
predicates
nondeterm rep(I,Z,A,K)
clauses
rep([],_,_,[]).
rep([Z|T1],Z,A,[A|T2]):- rep(T1,Z,A,T2).
rep([H|T1],Z,A,[H|T2]) :- rep(T1,Z,A,T2).
goal
rep([1,2,3],2,4,X).