Prolog - 找到增长最快的子序列

时间:2015-09-14 13:21:28

标签: list prolog clpfd

我想在Prolog中解决以下练习:

  

对于整数列表Zsmax_sequence(Zs,Xs)找到longest increasing subsequence Xs

示例查询:

?- 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).

我想知道我对这个问题的处理方法是否正确。 谢谢你的帮助!

2 个答案:

答案 0 :(得分:3)

TL; DR:解决高层问题:惯用思考;并且不要重新发明轮子:)

使用

:- use_module(library(clpfd)).

我们继续采取以下两个步骤:

  1. 我们首先将 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]].
    
  2. 我们只对最大尺寸的子列表感兴趣。 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].
    
  3. 那就是它!让我们把它放在一起并定义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,第一部分。