我们希望构建一个获取列表L
和数字N
的谓词,如果N
是列表L
中最长序列的长度,则为真。
例如:
?- ls([1,2,2,4,4,4,2,3,2],3).
true.
?- ls([1,2,3,2,3,2,1,7,8],3).
false.
为此我建了 -
head([X|S],X). % head of the list
ls([H|T],N) :- head(T,X),H=X, NN is N-1 , ls(T,NN) . % if the head equal to his following
ls(_,0) :- !. % get seq in length N
ls([H|T],N) :- head(T,X) , not(H=X) ,ls(T,N). % if the head doesn't equal to his following
概念很简单 - 检查头部是否等于他的跟随,如果是,继续尾部并递减N
。
我检查了我的代码并且效果很好(忽略了N = 1
) -
ls([1,2,2,4,4,4,2,3,2],3).
true ;
false .
但是true
答案并不是有限的,之后会有更多的答案,我怎么能让它回归有限的答案呢?
答案 0 :(得分:3)
Prolog-wise,你有一些问题。一个是你的谓词仅在两个参数都被实例化时才起作用,这对Prolog来说是令人失望的。另一个是你的风格 - head/2
并没有在[H|T]
上添加任何内容。我也认为这个算法存在根本缺陷。我不认为您可以确定列表尾部不存在较长的序列,而不保留猜测长度的未更改副本。换句话说,@ Zakum指出的第二件事,我认为不会有一个简单的解决方案。
这就是我如何处理这个问题。首先是一个辅助谓词,用于获取最多两个值:
max(X, Y, X) :- X >= Y.
max(X, Y, Y) :- Y > X.
现在大多数工作sequence_length/2
被委托给一个循环,除了空列表的基本情况:
sequence_length([], 0).
sequence_length([X|Xs], Length) :-
once(sequence_length_loop(X, Xs, 1, Length)).
对once/1
的调用确保我们只能得到一个答案。这将阻止谓词有效地生成带序列的列表,同时也使谓词具有确定性,这是您所希望的。 (它与切割良好的切割具有相同的效果)。
循环的基本情况:将累加器复制到输出参数:
sequence_length_loop(_, [], Length, Length).
归纳案例#1:我们有另一个相同值的副本。增加累加器并重复。
sequence_length_loop(X, [X|Xs], Acc, Length) :-
succ(Acc, Acc1),
sequence_length_loop(X, Xs, Acc1, Length).
归纳案例#2:我们有不同的价值。计算列表其余部分的序列长度;如果它比我们的累加器大,那就用它;否则,请使用累加器。
sequence_length_loop(X, [Y|Xs], Acc, Length) :-
X \= Y,
sequence_length([Y|Xs], LengthRemaining),
max(Acc, LengthRemaining, Length).
这就是我如何解决这个问题。我不知道它对你是否有用,但我希望你能从中收集一些东西。
答案 1 :(得分:2)
如何在最后一条规则中添加中断?
head([X|S],X). % head of the list
ls([H|T],N) :- head(T,X),H=X, NN is N-1 , ls(T,NN) . % if the head equal to his following
ls(_,0) :- !. % get seq in length N
ls([H|T],N) :- head(T,X) , not(H=X) ,ls(T,N),!. % if the head doesn't equal to his following
虽然我不是Prolog专家,但对我有用。
//编辑: btw。试试
14 ?- ls([1,2,2,4,4,4,2,3,2],2).
true ;
false.
对我来说看起来不对,没有检查N是否是最长的序列。或者我的要求是错误的?
答案 2 :(得分:2)
您的代码正在检查列表中是否存在至少一系列指定长度的元素。在访问列表时,您需要更多参数来保持搜索状态:
ls([E|Es], L) :- ls(E, 1, Es, L).
ls(X, N, [Y|Ys], L) :-
( X = Y
-> M is N+1,
ls(X, M, Ys, L)
; ls(Y, 1, Ys, M),
( M > N -> L = M ; L = N )
).
ls(_, N, [], N).