Prolog中的子列表谓词

时间:2017-03-22 13:25:32

标签: recursion prolog logic

我正在尝试在Prolog中定义谓词sublist(X,Y),当列表X的所有元素都出现在列表Y中时,它们的顺序与它们中的顺序相同X

我的方法是取X的头部,在Y中找到头部的第一个实例,然后在第一个实例之前剪切列表,然后用{{1直到尾部等于空列表。

我编写了帮助谓词X,如果cut(X,Y,Z)是在列表ZX的第一个实例之前切割所有内容的结果列表,则为真。< / 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]

我没有看到我的错误。有人能指出我吗?

1 个答案:

答案 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|...] ;