在Prolog中将列表拆分为两个长度相等的列表

时间:2014-04-10 18:10:40

标签: prolog

我正在Prolog中编写一个谓词,将列表分成两个相等的长度列表。例如:

div([1,2,3,4] , X , Y).
X = [1,2].
Y = [3,4].

这是我的代码,但它不起作用:

div(L , L1 , L):- length(L) == length(L1).
div([ H | T ] , [ H | T1] , L2):- div(T , T1 , L2).

6 个答案:

答案 0 :(得分:5)

可能只是:

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

读作"附加列表A和列表B得到原始列表L,A的长度是某个值N,并且B的长度是相同的值N"。

答案 1 :(得分:5)

有趣的是这种分裂不使用长度:

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

split(B, [], [], B).

split([H|T], [_, _|T1], [H | T2], B) :-
    split(T, T1, T2, B).

对于100 000个元素的列表,它使用50 001推断但是0,016个CPU,对于相同的列表,潜伏者的代码使用50 015推理和0,000个CPU。

答案 2 :(得分:2)

length(L) == length(L1)

不是你如何比较Prolog中的列表长度。它会比较''terms''length(L)length(L1)而不解释它们,即不调用任何谓词。要比较长度,请执行

length(L, N), length(L1, N)

如果你解决了这个问题,你的程序应该更接近工作。

答案 3 :(得分:2)

我喜欢谢尔盖的优雅和简约的解决方案(+1)。这是另一种方法,它不太优雅,有利于进一步提高效率,因为它修剪了查询append的情况。如果AB被取消,那么我们让他们的长度驱动这个过程。否则,我们让L的长度驱动它:

div(L, A, B) :-
    (   \+ground(A),
        \+ground(B)
    ->  length(L, N),
        HalfN is N div 2
    ;   true
    ),
    length(A, HalfN),
    length(B, HalfN),
    append(A, B, L).

这将产生,例如:

| ?-  div2(L, A, B).

A = []
B = []
L = [] ? ;

A = [C]
B = [D]
L = [C,D] ? ;

A = [C,D]
B = [E,F]
L = [C,D,E,F] ?
...

| ?- div([1,2,3|T], A, B).

A = [1,2]
B = [3,C]
T = [C] ? ;

A = [1,2,3]
B = [C,D,E]
T = [C,D,E] ? ;
...

| ?- div(L, [1,2], B).

B = [A,C]
L = [1,2,A,C]

yes
| ?- div([1,2|T], [1,2], [3,4]).

T = [3,4]

yes
| ?-

答案 4 :(得分:0)

就是这样,

div(L,L1,L2) :- length(L,Len), N is Len/2, split(L,L1,L2,N).
split([H|T],[H|L1],L2,N):- N1 is N-1, split(T,L1,L2,N1).
split(T,[],T,0).

答案 5 :(得分:0)

{{1}}

就是这样,适用于奇怪的长度:)