Prolog-第一个列表是第二个列表的子列表,同时保持顺序?

时间:2019-09-25 14:29:20

标签: list prolog sublist

我想检查列表L1中的元素是否连续出现并且以相同的顺序出现在列表L2中。

例如-check([b,c],[a,b,c,d])必须返回true,而check([b,d],[a,b,c,d])必须返回false < / p>

我查看了类似的帖子Prolog - first list is sublist of second list?,并尝试了类似的解决方案,但是每当我尝试检查是否存在元素时,便无法检查订购是否连续

check( [], _ ).
check( [X|XS], [X|XSS] ) :- sublist( XS, XSS ).
check( [X|XS], [_|XSS] ) :- sublist( [X|XS], XSS ).

如果我尝试检查订购是否正确,那么我的代码就坏了。

check( [], _ ).
check( [X|XS], [X|XSS] ) :- sublist( XS, XSS ).

3 个答案:

答案 0 :(得分:3)

使用myapp谓词的事实标准定义的替代解决方案:

append/3

通话示例:

check(SubList, List) :-
    append(Prefix, _, List),
    append(_, SubList, Prefix).

我们还可以使用此定义来生成子列表-列表对:

| ?- check([b,d],[a,b,c,d]).

no

| ?- check([b,c],[a,b,c,d]).

true ? ;
no

| ?- check([b,c],[a,b,c,d,b,c,f]).

true ? ;
true ? ;
no

此问题还使您有机会了解谓词的终止属性。作为实验,交换| ?- check(SubList, List). SubList = [] ? ; List = [A|_] SubList = [A] ? ; List = [_|_] SubList = [] ? ; List = [A,B|_] SubList = [A,B] ? ; List = [_,A|_] SubList = [A] ? ; List = [_,_|_] SubList = [] ? ; List = [A,B,C|_] SubList = [A,B,C] ? ; List = [_,A,B|_] SubList = [A,B] ? ; ... 调用的顺序,然后检查回溯时发生了什么,例如前两个示例调用。

答案 1 :(得分:3)

我们可以利用append/2 [swi-doc]来编写单行代码:

subsequence(X, Y) :-
    append([_,X,_], Y).

或者我们可以实现一个subsequence/4,它将在子序列前后的列表中统一两个变量PrefixSuffix

subsequence(X, Y, Prefix, Suffix) :-
    append([Prefix,X,Suffix], Y).

因此,这里有两个无关紧要的变量,它们将收集子序列前后的前缀和后缀。

答案 2 :(得分:2)

有趣的问题!我对它花了多少代码感到惊讶,因此可能有比这更好的解决方案。

首先,我们需要一个助手来坚持一个列表是另一个列表的前缀。基本情况是我们用尽了前缀列表。归纳的情况是当前项目匹配,并且两个列表的其余部分都是前缀匹配。

prefix([X|Xs], [X|Ys]) :- prefix(Xs, Ys).
prefix([], _).

现在找到连续的子列表就等于在列表中搜索前缀匹配项。如果当前项目匹配,则具有前缀是匹配项:

consecutive_sublist([X|Xs], [X|Ys]) :- prefix(Xs, Ys).

否则,我们只丢弃搜索目标的此元素,然后在子列表上重试:

consecutive_sublist(Prefix, [_|Ys]) :- consecutive_sublist(Prefix, Ys).