我正在尝试在Prolog中定义谓词sublist(X,Y)
,当列表X
的所有元素都出现在列表Y
中时,它们的顺序与它们中的顺序相同X
。
我的方法是取X
的头部,在Y
中找到头部的第一个实例,然后在第一个实例之前剪切列表,然后用{{1直到尾部等于空列表。
我编写了帮助谓词X
,如果cut(X,Y,Z)
是在列表Z
中X
的第一个实例之前切割所有内容的结果列表,则为真。< / p>
我的代码如下:
Y
当我查询
时cut(_,[],[_|_]) :- false.
cut(X,[H|T],[H|T]) :- X = H, !.
cut(X,[_|T],Y) :- cut(X,T,Y).
sublist([],[]).
sublist([],[_|_]).
sublist([A|B],C) :- cut(A,C,Z), sublist(B,Z).
而不是给出?- sublist(L,[1,2,3]).
Prolog的所有子列表,而不是给出以下输出:
[1,2,3]
我没有看到我的错误。有人能指出我吗?
答案 0 :(得分:2)
简短回答:cut/3
如果找到元素,则从列表中不会弹出。
第一个答案L = [].
是第二个句子触发的结果。现在,下一个答案由最后一个子句生成。那么会发生什么:
sublist(A,[1,2,3]) :- % C = [1,2,3]
cut([A|B],[1,2,3],[H|T]) :- % H = 1, T = [2,3], Z = [1,2,3]
A = H, % A=1
!.
sublist(B,[1,2,3]).
因此,cut/3
的第二个句子触发,第二个和第三个参数是等价的,因此cut/3
不是&#34; pop&#34;从列表中。
通过以下方式从列表中弹出解决此问题并保证进展的方法:
cut(_,[],[_|_]) :- false.
cut(H,[H|T],T) :-
!.
cut(X,[_|T],Y) :-
cut(X,T,Y).
(我也冒昧地用X
替换H
在条款的头部,使它更优雅。现在它生成:
?- sublist(L,[1,2,3]).
L = [] ;
L = [1] ;
L = [1, 2] ;
L = [1, 2, 3] ;
false.
请注意,答案不会生成所有列表:例如L = [2,3]
也是有效答案。这不起作用的原因是因为cut/3
具有!
,因此不允许引入其他元素。您可以通过以下方式解决此问题:
cut(_,[],[_|_]) :- false.
cut(H,[H|T],T).
cut(X,[_|T],Y) :-
cut(X,T,Y).
现在我们获得:
?- sublist(L,[1,2,3]).
L = [] ;
L = [1] ;
L = [1, 2] ;
L = [1, 2, 3] ;
L = [1, 3] ;
L = [2] ;
L = [2, 3] ;
L = [3] ;
false.
尽管如此,您可以在不使用帮助谓词的情况下非常优雅地解决问题。我们可以先构造一个验证/创建列表的谓词:
list([]).
list([_|T]) :-
list(T).
接下来我们说如果X
为空,你真的不在乎右边的那种列表:
sublist([],L) :-
list(L).
最后如果X
不为空,我们需要在某处获得HX
({1}}的头部。如果我们找到它,我们可以决定接受&#34;接受&#34;它,并弹出两个列表,或者我们可以决定寻找另一个X
,例如:
HX
最后一个子句中的sublist([HX|TX],[HX|TY]) :-
sublist(TX,TY).
sublist(X,[_|TY]) :-
X = [_|_],
sublist(X,TY).
并非绝对必要,但会阻止使用X = [_|_]
子句生成重复结果。
或者把它放在一起:
sublist([],X)
这会产生:
list([]).
list([_|T]) :-
list(T).
sublist([],L) :-
list(L).
sublist([HX|TX],[HX|TY]) :-
sublist(TX,TY).
sublist(X,[_|TY]) :-
X = [_|_],
sublist(X,TY).
或者:
?- sublist(L,[1,2,3]).
L = [] ;
L = [1] ;
L = [1, 2] ;
L = [1, 2, 3] ;
L = [1, 3] ;
L = [2] ;
L = [2, 3] ;
L = [3] ;
false.
或者:
?- sublist([1,2,3],L).
L = [1, 2, 3] ;
L = [1, 2, 3, _G2440] ;
L = [1, 2, 3, _G2440, _G2443] ;
L = [1, 2, 3, _G2440, _G2443, _G2446] ;
L = [1, 2, 3, _G2440, _G2443, _G2446, _G2449] ;
L = [1, 2, 3, _G2440, _G2443, _G2446, _G2449, _G2452] ;
L = [1, 2, 3, _G2440, _G2443, _G2446, _G2449, _G2452, _G2455] ;
L = [1, 2, 3, _G2440, _G2443, _G2446, _G2449, _G2452, _G2455|...] ;