Prolog检查数字列表是有序的

时间:2012-12-04 16:42:33

标签: prolog

我希望能够获取一个数字列表并获得有序的最大数字序列。例如:

?- in_order([1,2,3,4,5],N).
N = 5.                              % expected result

?- in_order([1,2,5,6,7,8,4],N).
N = 4.                              % expected result

到目前为止,我已经生成了一些基本代码来计算一系列数字的长度,但是一旦列表为空,它就会返回轨道,因此返回的数字为N,与列表中的第一个元素相同。我知道我需要停止追踪,但似乎无法做到。有人会善意地指出我正确的方向。

到目前为止我的代码(都是有点hacky):

in_order([],_) :-
   !.
in_order([H|T],N):-
   (  var(N), 
      N is H 
   ;  true
   ),
   H = N,
   M is N+1,
   in_order(T,M).

我确实理解我当前的解决方案在给出的第二个示例中不起作用,并且该方面的指针将再次有用,因为我不太确定如何解决这个问题。我正在使用SICStus Prolog。

非常感谢提前!

4 个答案:

答案 0 :(得分:2)

让我称之为zs_maxInOrder/2的关系,它基于clpfd 并使用reified constraints

:- use_module(library(clpfd)).

zs_maxInOrder([]    ,0).
zs_maxInOrder([Z|Zs],N) :-
    zs_prev_n_max0_max(Zs,Z,1,1,N).            % use "lagging" 

zs_prev_n_max0_max([]     ,_ ,_ ,M ,M).
zs_prev_n_max0_max([Z1|Zs],Z0,N0,M0,M) :-
    Z1 #= Z0 + 1 #<=> B,                       % with SWI-Prolog use `(#<==>)/2`
    N1 #= N0 * B + 1,
    M1 #= max(M0,N1),
    zs_prev_n_max0_max(Zs,Z1,N1,M1,M).

让我们看一下使用SICStus Prolog 4.3.1:

?- zs_maxInOrder([1,2,3,4,5],N).
N = 5 ? ;
no
?- zs_maxInOrder([1,2,5,6,7,8,4],N).
N = 4 ? ;
no

角落案件怎么样?

?- zs_maxInOrder([1],N).
N = 1 ? ;
no
?- zs_maxInOrder([],N).
N = 0 ? ;
no

答案 1 :(得分:1)

你的尝试失败了,因为你混合了不同的东西。当你写

N is H

您基本上是在输出列表中的一个元素。这是你在任何情况下都不想做的事情。基本情况也是错误的,应该是“空列表的有序序列为零”。

尝试使用“累加器”参数来跟踪以当前头H终止的连续元素。

答案 2 :(得分:1)

这是解决问题的一个相当强力的解决方案:P(我知道我会受到批评,但我无法抗拒使用更高阶的谓词)。

my_prefix(List,Prefix) :- 
   append(Prefix,_,List).

my_suffix(List,Suffix) :- 
   append(_,Suffix,List).

my_sublist(List,Sublist) :-
   my_suffix(List,Suffix),
   my_prefix(Suffix,Sublist).

all_sublists(List,AllSublists) :- 
   findall(Sub,my_sublist(List,Sub),AllSublists).

good_list([]) :- 
   !.
good_list([H]) :- 
   !.
good_list([H1,H2|T]) :- 
   H1 is H2-1,
   good_list([H2|T]),
   !.

in_order(List,Length) :-
   all_sublists(List,AllSublists),
   findall(L,(member(Sublist,AllSublists),
              good_list(Sublist),
              length(Sublist,L)),
             InOrderSizes),
   max_list(InOrderSizes,Length).

答案 3 :(得分:0)

  

“空列表的有序序列为零”。

谢谢你。它让我走上正轨(我认为)

到目前为止,这是我的解决方案:

in_order([], _, 0).
in_order([H|T], Prev, N):-
  % Split the list
  in_order(T, H, M),
  % Increment the expected Head value
  H1 is Prev + 1,
    (
      H = H1,
      N is M + 1
    ;
      M1 is M + 1,
      format('M1 is ~w~n', [M1]),
      N is 0
  ).

我添加了格式,以便我可以看到最后阶段正在打印的内容,并且我得到输入值[1,2,5,6,7,8,4]的值1和4 - 是正确的。谓词返回2(序列的最后一个长度),但当我回溯试图获得更多答案时,我没有得到值4或1.我认为我非常接近答案,任何额外的最终帮助将是赞赏。

非常感谢

相关问题