我正在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).
答案 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
的情况。如果A
或B
被取消,那么我们让他们的长度驱动这个过程。否则,我们让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}}
就是这样,适用于奇怪的长度:)