Prolog,将列表分成两个列表

Prolog, split list into two lists

列表有问题。我需要做的是将一个列表 [1,-2,3,-4] 拆分为两个列表 [1,3][-2,-4]。我的代码如下所示:

lists([],_,_).
lists([X|Xs],Y,Z):- lists(Xs,Y,Z), X>0 -> append([X],Y,Y) ; append([X],Z,Z).

我得到

Y = [1|Y],
Z = [-2|Z].

我做错了什么?

参考这个:

domains
    list=integer*

predicates
    split(list,list,list)
clauses
    split([],[],[]).
    split([X|L],[X|L1],L2):-
        X>= 0,
        !,    
        split(L,L1,L2).

    split([X|L],L1,[X|L2]):-
        split(L,L1,L2).

Output :

目标: split([1,2,-3,4,-5,2],X,Y)
解法: X=[1,2,4,2], Y=[-3,-5]

看看有没有帮助。

只是为了多样化,这也可以用 DCG 来完成,这样的问题很容易阅读:

split([], []) --> [].
split([X|T], N) --> [X], { X >= 0 }, split(T, N).
split(P, [X|T]) --> [X], { X < 0 }, split(P, T).

split(L, A, B) :-
    phrase(split(A, B), L).

如:

| ?- split([1,2,-4,3,-5], A, B).

A = [1,2,3]
B = [-4,-5] ? ;

no

它还提供了所有可能的反向解决方案:

| ?- split(L, [1,2,3], [-4,-5]).

L = [1,2,3,-4,-5] ? ;

L = [1,2,-4,3,-5] ? ;

L = [1,2,-4,-5,3] ? ;

L = [1,-4,2,3,-5] ? ;

L = [1,-4,2,-5,3] ? ;

L = [1,-4,-5,2,3] ? ;

L = [-4,1,2,3,-5] ? ;

L = [-4,1,2,-5,3] ? ;

L = [-4,1,-5,2,3] ? ;

L = [-4,-5,1,2,3] ? ;

(2 ms) no

Gaurav 的解决方案也将执行此操作,如果剪切被删除并且显式 X < 0 检查置于 split/3 谓词的第三个子句中。

您的代码中有几处需要更正。 如果您喜欢紧凑(可读)代码,一种可能性是

lists([],[],[]).
lists([X|Xs],Y,Z) :-
  ( X>0 -> (Y,Z)=([X|Ys],Zs) ; (Y,Z)=(Ys,[X|Zs]) ), lists(Xs,Ys,Zs).

但是由于 (SWI)Prolog 提供了库来处理常见的列表处理任务,因此可以像

lists(A,B,C) :- partition(<(0),A,B,C).

如果您的 Prolog 系统提供 you could preserve 。想知道怎么做吗? 继续阅读!

我们取@CapelliC写的lists/3的第二个定义 as a starting point, and replace partition/4 by tpartition/4 and (<)/2 by (#<)/3:

lists(A,B,C) :- tpartition(#<(0),A,B,C).

让我们运行一个示例查询!

?- As = [0,1,2,-2,3,4,-4,5,6,7,0], lists(As,Bs,Cs).
As = [0,1,2,-2,3,4,-4,5,6,7,0],
Bs = [  1,2,   3,4,   5,6,7  ],
Cs = [0,    -2,    -4,      0].

当我们使用单调代码时,对于更一般的查询,我们会得到逻辑上合理的答案:

?- As = [X,Y], lists(As,Bs,Cs).
As = [X,Y], Bs = [X,Y], Cs = [   ], X in   1..sup, Y in   1..sup ;
As = [X,Y], Bs = [X  ], Cs = [  Y], X in   1..sup, Y in inf..0   ;
As = [X,Y], Bs = [  Y], Cs = [X  ], X in inf..0  , Y in   1..sup ;
As = [X,Y], Bs = [   ], Cs = [X,Y], X in inf..0  , Y in inf..0   . 

给你。它拆分一个列表,无论项目数是奇数还是偶数都没有关系。

div(L, A, B) :-
    append(A, B, L),
    length(A, N),
    length(B, N).

div(L, A, B) :-
    append(A, B, L),
    length(A, N),
    N1 is N + 1,
    length(B, N1).

div(L, A, B) :-
    append(A, B, L),
    length(A, N),
    N1 is N - 1,
    length(B, N1).