我想检查列表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 ).
答案 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
,它将在子序列前后的列表中统一两个变量Prefix
和Suffix
:
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).