我实现了获取列表子列表的函数,例如:
sublist([1,2,4], [1,2,3,4,5,1,2,4,6]).
true
sublist([1,2,4], [1,2,3,4,5,1,2,6]).
false
看看我的解决方案:
my_equals([], _).
my_equals([H1|T1], [H1|T2]) :- my_equals(T1, T2).
sublist([], _).
sublist(L1, [H2|T2]) :- my_equals(L1, [H2|T2]); sublist(L1, T2).
你能给我另一个解决方案吗?也许存在一些预定义的谓词my_equals
?
答案 0 :(得分:4)
您可以使用append/3统一子列表,如下所示:
sublist(SubList, List):-
append(_, Tail, List),
append(SubList, _, Tail).
第一次拨打append/3
会将List拆分为两部分(即从列表中删除部分"前导"项目。
对append/3
的第二次调用将检查SubList本身是否为Tail的子列表。
正如@ false&f; s表明,至少在地面条件下交换目标会更好,
sublist(SubList, List):-
append(SubList, _, Tail),
append(_, Tail, List).
答案 1 :(得分:4)
There's also a DCG approach to the problem:
substr(Sub) --> seq(_), seq(Sub), seq(_).
seq([]) --> [].
seq([Next|Rest]) --> [Next], seq(Rest).
Which you would call with:
phrase(substr([1,2,4]), [1,2,3,4,5,1,2,4,6]).
You can define:
sublist(Sub, List) :-
phrase(substr(Sub), List).
So you could call it by, sublist([1,2,4], [1,2,3,4,5,1,2,4,6]).
.
substr(Sub) --> ..., seq(Sub), ... .
... --> [] | [_], ... .
Yes, you can have a predicate named ...
. :)
subseq
(subsequence) to substr
(substring) since the meaning of "subsequence" embraces non-contiguous sequences.
答案 2 :(得分:2)
这是Lurkers的另一种解决方案,它稍快一点, 假设S的长度比L短得多,因此短语/ 3 DCG 翻译时间可以忽略不计:
sublist(S, L) :-
phrase((..., S), L, _).
如果S = [X1,..,Xn],它会将DCG转换为匹配I = [X1,..,Xn | O] 在执行之前,因此将my_equals / 2完全委托给Prolog 统一。以下是一个示例运行:
?- phrase((..., [a,b]), [a,c,a,b,a,c,a,b,a,c], X).
X = [a, c, a, b, a, c] ;
X = [a, c] ;
false.
再见
P.S。:也适用于其他模式S而不仅仅是终端。
答案 3 :(得分:0)
可能存在一些预定义的谓词
如果您的Prolog已从库(列表)附加/ 2:
sublist(S, L) :- append([_,S,_], L).
另一个相当紧凑的定义,可用于每个(我猜)Prolog那里:
sublist(S, L) :- append(S, _, L).
sublist(S, [_|L]) :- sublist(S, L).
答案 4 :(得分:0)
原始问题中的解决方案是有效的,正如已经说过的那样,“my_equals”可以被“append”和“sublist”循环替换为另一个附加提供原始列表的切片。
然而,prolog是(或者是)关于人工智能。任何人都可以立即回答“不”这个例子:
sublist([1,1,1,2], [1,1,1,1,1,1,1,1,1,1] ).
因为一个人,通过对列表的简单观察,推断出它的某些特征,就像没有“2”一样。
相反,这个提案在这种情况下效率很低。例如,在DNA分析领域,只研究了四个元素的长序列,这种算法不适用。
可以进行一些简单的更改,目标是首先查看最强的条件。例如:
/* common( X, Y, C, QX, QY ) => X=C+QX, Y=C+QY */
common( [H|S2], [H|L2], [H|C2], DS, DL ) :- !,
common( S2, L2, C2, DS, DL ).
common( S, L, [], S, L ).
sublist( S, L ) :-
sublist( [], S, L ).
sublist( P, Q, L ) :- /* S=P+Q */
writeln( Q ),
length( P, N ),
length( PD, N ), /* PD is P with all unbound */
append( PD, T, L ), /* L=PD+T */
common( Q, T, C, Q2, _DL ), /* S=P+C+Q2; L=PD+C+_DL */
analysis( L, P, PD, C, Q2 ).
analysis( _L, P, P, _C, [] ) :- !. /* found sublist */
analysis( [_|L2], P, _PD, C, [] ) :- !,
sublist( P, C, L2 ).
analysis( [_|L2], P, _PD, C, Q2 ) :-
append( P, C, P2 ),
sublist( P2, Q2, L2 ).
让我们试一试:
?- sublist([1,1,1,2], [1,1,1,1,1,1,1,1,1,1]).
[1,1,1,2]
[2]
[2]
[2]
[2]
[2]
[2]
[2]
[2]
false.
看看“分析”如何决定更好地寻找“2”。
显然,这是一个强烈简化的解决方案,在实际情况下,可以进行更好的“分析”,找到的模式必须更灵活(提案仅限于原始S模式尾部的模式)。