您的程序将许多不同的问题组合到一个谓词中。让我们试着把它们分开一点。另外,我假设您正在搜索包含相同元素的两个或多个元素的最大子列表。
让我们从您想要的近似值开始:识别子列表。不要担心这太宽泛了,我们稍后会完善它。为此,我将使用 DCG。非终结符seq//1
描述任意序列。
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
这是一个非常有用的非终端!
?- 短语((seq(Prefix),seq(Sublist),seq(Postfix)),
[a,a,b,2,2,2,a+1,a+1,s(1,2)])。
前缀 = 子列表,子列表 = [],
后缀 = [a,a,b,2,2,2,a+1,a+1,s(1,2)] ;
前缀 = [],
子列表 = "a" ,
后缀 = [a,b,2,2,2,a+1,a+1,s(1,2)] ...
这两个答案都不是预期的,我们只想要长度为 2 或更多的子列表,因此我们必须稍微限制该定义。说,通过要求Sublist
至少应该包含两个元素。那就是Sublist = [_,_|_]
。
?- 子列表 = [_,_|_],
短语((序列(前缀),序列(子列表),序列(后缀)),
[a,a,b,2,2,2,a+1,a+1,s(1,2)])。
子列表 = "aa",
前缀 = [],
后缀 = [b,2,2,2,a+1,a+1,s(1,2)] ;
子列表 = "aab" ,
前缀 = [],
后缀 = [2,2,2,a+1,a+1,s(1,2)] ...
第一个答案显示了我们正在搜索的子列表。但第二个仍然不正确:子列表的所有元素都应该相等。最简单的方法是使用maplist/2
:
?- maplist(=(_),Es)。
Es = [] ;
Es = [_G221] ;
Es = [_G221,_G221] ;
Es = [_G221,_G221,_G221]
有几个地方我们可以说明这个要求。我会把它放在尽可能早的地方:
?- 子列表 = [_,_|_],
短语((序列(前缀),
seq(子列表),{maplist(=(_),子列表)},
序列(后缀)),
[a,a,b,2,2,2,a+1,a+1,s(1,2)])。
子列表 = "aa",
前缀 = [],
后缀 = [b,2,2,2,a+1,a+1,s(1,2)] ;
子列表 = [2,2],
前缀 = "aab",
后缀 = [2,a+1,a+1,s(1,2)] ;
子列表 = [2,2,2],
前缀 = "aab",
后缀 = [a+1,a+1,s(1,2)] ;
子列表 = [2,2],
前缀 = [a,a,b,2],
后缀 = [a+1,a+1,s(1,2)] ;
子列表 = [a+1,a+1],
前缀 = [a,a,b,2,2,2],
后缀 = [s(1,2)] ;
错误的。
所以现在,所有子列表都包含相同的元素。唉,我们得到了两个[2,2]
和[2,2,2]
作为子列表。我们只想要最大的子列表。那么我们如何描述最大子列表是什么?
一种方法是查看我们的子列表的前面:我们的子列表中不能有完全相同的元素。因此,要么前面没有任何东西(epsilon),要么以与我们不同的元素结束的序列。
difel(_E,[]).
difel(E, Es) :- dif(E,F), phrase((seq(_), [F]), Es).
?- 子列表 = [_,_|_],
短语((序列(前缀),{difel(E,前缀)},
seq(子列表),{maplist(=(E),子列表)},
序列(后缀)),
[a,a,b,2,2,2,a+1,a+1,s(1,2)])。
子列表 = "aa",
前缀 = [],
E = 一个,
后缀 = [b,2,2,2,a+1,a+1,s(1,2)] ;
子列表 = [2,2],
前缀 = "aab",
E = 2,
后缀 = [2,a+1,a+1,s(1,2)] ;
子列表 = [2,2,2],
前缀 = "aab",
E = 2,
后缀 = [a+1,a+1,s(1,2)] ;
子列表 = [a+1,a+1],
前缀 = [a,a,b,2,2,2],
E = a+1,
后缀 = [s(1,2)] ;
错误的。
少一个错误答案。最后还有一个潜伏在身边。
?- 子列表 = [_,_|_],
短语((序列(前缀),{difel(E,前缀)},
seq(子列表),{maplist(=(E),子列表)},
( [] | [F],{dif(E,F)},seq(_) ) ),
[a,a,b,2,2,2,a+1,a+1,s(1,2)])。
子列表 = "aa",
前缀 = [],
E = 一个,
F = b;
子列表 = [2,2,2],
前缀 = "aab",
E = 2,
F = a+1 ;
子列表 = [a+1,a+1],
前缀 = [a,a,b,2,2,2],
E = a+1,
F = s(1,2) ;
错误的。
这并不是你想要的:你只是想要长度。为此,添加length([_|Prefix],I), length(Sublist,Len)
.
所以这是最终的定义:
高原(Xs,I,Len):-
子列表 = [_,_|_],
短语((序列(前缀),{difel(E,前缀)},
seq(子列表),{maplist(=(E),子列表)},
( [] | [F],{dif(E,F)},seq(_) ) ),
Xs),
长度([_|前缀],I),
长度(子列表,Len)。