我想在Prolog中解决以下练习:
对于整数列表
Zs
,max_sequence(Zs,Xs)
找到longest increasing subsequenceXs
。
示例查询:
?- max_sequence([1,2,1,2,3,4,2,1,2,1],Xs). Xs = [1,2,3,4]. % expected result ?- max_sequence([1,2,1,2,3,4,2,1,6,7,7,2,1,8],Xs). Xs = [1,2,3,4,6,7,8]. % expected result
我无法理解为什么......但我的代码错了,结果总是false
。
max_sequence(L,R) :-
cresc(L,[],R).
cresc([],[],[]).
cresc([H|T],C,[H|C]) :-
maxList(H,C),
\+ member(H,C),
cresc(T,C,C).
cresc([H|T],C,C) :-
member(H,C),
cresc(T,C,C).
cresc([H|T],C,C) :-
\+ maxList(H,C),
cresc(T,C,C).
maxList(_,[]).
maxList(N, [H|T]) :-
N>H,
maxList(N,T).
我想知道我对这个问题的处理方法是否正确。 谢谢你的帮助!
答案 0 :(得分:3)
TL; DR:解决高层问题:惯用思考;并且不要重新发明轮子:)
使用clpfd!
:- use_module(library(clpfd)).
我们继续采取以下两个步骤:
我们首先将meta-predicate splitlistIfAdj/3
与(#>=)/3
一起使用:
?- splitlistIfAdj(#>=,[1,2,2,2,1,2,3,4,2,1,3,5,7,1],Zss).
Zss = [[1,2],[2],[2],[1,2,3,4],[2],[1,3,5,7],[1]].
我们只对最大尺寸的子列表感兴趣。 max_of_by/3
可以排除所有其他内容:
?- max_of_by(Xs,[[1,2],[2],[2],[1,2,3,4],[2],[1,3,5,7],[1]],length).
Xs = [1,2,3,4]
; Xs = [1,3,5,7].
那就是它!让我们把它放在一起并定义list_longest_ascending_sublist/2
:
list_longest_ascending_sublist(Xs,Zs) :-
splitlistAdjIf(#>=,Xs,Yss),
max_of_by(Zs,Yss,length).
示例查询:
?- list_longest_ascending_sublist([1,2,2,2,1,2,3,4,2,1,3,5,7,1],Zs). Zs = [1,2,3,4] ; Zs = [1,3,5,7]. ?- list_longest_ascending_sublist([1,2,2,3,4,5,6,2,1,2,3,4,2,1,3,5,7,1],Zs). Zs = [2,3,4,5,6].
答案 1 :(得分:0)
我根本无法理解您的方法,但在Trace
中使用swi-prolog
命令,您可以逐步查看程序执行情况,以查看其失败的位置。尝试一下,你会看到代码出了什么问题。
无论如何,这可能是一种可能的解决方案:从列表的第一个元素开始,您应该只收集一个列表,直到元素增加,同时保持该子列表的长度,这是第一个候选者。然后再次开始收集一个新列表及其长度,如果比候选人长,则切换它们,依此类推...... 在这里,您可以找到代码:max_seqs,第一部分。