如何在prolog中制作两个列表,一个是偶数,一个是奇数?

时间:2014-05-17 16:33:44

标签: prolog

我有一个问题。

我们有一个未排序的列表:

(1 4 5 3 6 7)

你能帮我制作2个名单吗?

一个奇数编号,增加的列表:

(1 3 5 7)

和另一个偶数编号,递减列表:

(6 4)

不要使用sort!

我在尝试计划。但是在prolog中,我不知道如何制作它。

下面:

   (define (split lst)
  (let loop ((a '()) (b  '()) (lst lst))
    (if (null? lst)
        (values a (reverse b))
        (let ((cur (car lst)))
          (if (odd? cur)
              (loop (cons cur a) b (cdr lst))
              (loop a (cons cur b ) (cdr lst))
              )))
   )
  )
(split '(1 2 3 4 5 6 7 8 9 10 11 12 13 14))

1 个答案:

答案 0 :(得分:2)

嗯,首先,我们可以很容易地将这些事情与这些事情分开:

separate_even_odd([], [], []).
separate_even_odd([X|Xs], [X|Even], Odd) :-
  0 is X mod 2,
  separate_even_odd(Xs, Even, Odd).
separate_even_odd([X|Xs], Even, [X|Odd]) :-
  1 is X mod 2,
  separate_even_odd(Xs, Even, Odd).

这不是非常有效 - 尾递归版本不会更难,并且使用条件表达式会更有效,但这似乎是一种非常直接的启动方式。这当然不能完全符合您的要求:

?- separate_even_odd([1,4,5,3,6,7], X, Y).
X = [4, 6],
Y = [1, 5, 3, 7]

由于我们无法排序,我们需要维护一个排序列表。基本案例列表由于是空的而排序,因此我们只需要想出一种方法将值插入到排序列表中,从而维护sort属性。在一种情况下这不是很难:

insert_into_sorted_list(X, [], [X]).
insert_into_sorted_list(X, [Y|Ys], [X, Y|Ys]) :-
  X =< Y.
insert_into_sorted_list(X, [Y|Ys], [Y|Zs]) :-
  X > Y,
  insert_into_sorted_list(X, Ys, Zs).

同样,基于相同的原因,这并不是特别有效。显而易见的下一步是复制和粘贴并更改方向,给它一个不同的名称,但这是Prolog,我们可以传递我们想要使用的运算符,并用call/2调用它。

insert_into_sorted_list(_,  X, [],     [X]).
insert_into_sorted_list(Op, X, [Y|Ys], Result) :-
  (   call(Op, X, Y) ->
      Result = [X, Y|Ys]
  ;   insert_into_sorted_list(Op, X, Ys, Zs),
      Result = [Y|Zs]
  ).

你可以看到它有效:

?- insert_into_sorted_list(=<, 8, [1,2,4,5,6], X).
X = [1, 2, 4, 5, 6, 8] 

?- insert_into_sorted_list(>, 8, [6,5,4,3,2,1], X).
X = [8, 6, 5, 4, 3, 2, 1].

?- insert_into_sorted_list(<, 8, [6,5,4,3,2,1], X).
X = [6, 5, 4, 3, 2, 1, 8] ;
false.

?- insert_into_sorted_list(<, 0, [1,2,4,5,6], X).
X = [0, 1, 2, 4, 5, 6].

?- insert_into_sorted_list(<, 3, [1,2,4,5,6], X).
X = [1, 2, 3, 4, 5, 6].

我怀疑你现在可以看到即将发生的事情:将insert_into_sorted_list/4separate_odd_even/3捆绑在一起:

separate_even_odd([], [], []).
separate_even_odd([X|Xs], Even, Odd) :-
    separate_even_odd(Xs, Even0, Odd0),
    (   0 is X mod 2 ->
        insert_into_sorted_list(>, X, Even0, Even),
        Odd = Odd0
    ;   insert_into_sorted_list(<, X, Odd0, Odd),
        Even = Even0
    ).

检查出来,它有效:

?- separate_even_odd([1,4,5,3,6,7], Even, Odd).
Even = [6, 4],
Odd = [1, 3, 5, 7]