另一个问题是,我有一个很好的工作“功能”用于删除:
remove([],X,[]) :- !.
remove([X|T],X,L1) :- !, remove(T,X,L1).
remove([H|T],X,[H|L1]) :- remove(T,X,L1).
但它不能像我希望它一样工作。 它删除元素甚至列表......
...但不会删除所有外观。这是目标:
remove([A,B,[C],[A,[B]],[[A,[B]]]],[A,[B]],X).
X=[A,B,[C],[]]
有什么想法吗?
答案 0 :(得分:5)
如果你想删除所有外观,例如,要删除([1,2,3,1],1,X)计算X = [2,3]只需用
替换第二个子句 remove([X|T],X,L1) :- remove(T,X,L1), !.
但是,您似乎希望a)使用应保留为变量的变量,以及b)从子列表中删除列表。
我们将首先解决b)问题。
remove([],_,[]) :- !.
remove(A,_,A) :- \+ (A = [_|_]), !.
remove([X|T],X,L1) :- remove(T,X,L1), !.
remove([H|T],X,[G|L1]) :- remove(H,X,G), remove(T,X,L1).
如您所见,我们向最后一个子句添加第二次递归调用以处理内部列表。此外,我们必须添加一个特例(第二个子句),因为第一个参数不一定是列表。
最后,要解决a)你需要使用"冻结" /"融化" Sterling和Shapiro的谓词。冻结用表达式#VAR(0),#VAR(1),...替换变量,而熔化则相反。熔化传统上称为melt_new
numvars('#VAR'(N),N,N1) :- N1 is N+1.
numvars(Term,N1,N2) :- nonvar(Term), functor(Term,_,N),
numvars(0,N,Term,N1,N2).
numvars(N,N,_,N1,N1).
numvars(I,N,Term,N1,N3) :- I<N, I1 is I+1,
arg(I1,Term,Arg), numvars(Arg,N1,N2),
numvars(I1,N,Term,N2,N3).
frz(A,B) :- frz(A,B,0).
frz(A,B,Min) :- copy_term(A,B), numvars(B,Min,_),!.
melt_new(A,B) :-
melt(A,B,Dictionary), !.
melt('$VAR'(N),X,Dictionary) :-
lookup(N,Dictionary,X).
melt(X,X,Dictionary) :-
constant(X).
melt(X,Y,Dictionary) :-
compound(X),
functor(X,F,N),
functor(Y,F,N),
melt(N,X,Y,Dictionary).
melt(N,X,Y,Dictionary) :-
N > 0,
arg(N,X,ArgX),
melt(ArgX,ArgY,Dictionary),
arg(N,Y,ArgY),
N1 is N-1,
melt(N1,X,Y,Dictionary).
melt(0,X,Y,Dictionary).
/*
lookup(Key,Dictionary,Value) :-
Dictionary contains the value indexed under Key.
Dictionary is represented as an ordered binary tree.
*/
lookup(Key,dict(Key,X,Left,Right),Value) :-
!, X = Value.
lookup(Key,dict(Key1,X,Left,Right),Value) :-
Key < Key1 , lookup(Key,Left,Value).
lookup(Key,dict(Key1,X,Left,Right),Value) :-
Key > Key1, lookup(Key,Right,Value).
顺便说一句,我真的推荐Sterling和Shapiro的书&#34; Prolog的艺术&#34;。 第15章讨论了熔化和冷冻。