我正在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).
我正在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).
可能只是:
div(L, A, B) :-
append(A, B, L),
length(A, N),
length(B, N).
same_length/2
不是ISO谓词。 - lurkerA
和 B
的长度来减少 append
的迭代次数:div(L, A, B) :- length(L, N), Half is N div 2, length(A, Half), length(B, Half), append(A, B, L)
。 - lurkerL
未绑定但其中一个 A
或 B
已绑定时。它会给出正确的解决方案,但在回溯寻找更多解决方案时会一直旋转。它可能可以修改以避免这种情况。然后就只是优雅与高效之间的权衡。当然,代码并不总是关于效率的。 :) - lurkerdiv(L, A, B) :-
split(L, L, A, B).
split(B, [], [], B).
split([H|T], [_, _|T1], [H | T2], B) :-
split(T, T1, T2, B).
split/4
使用列表本身作为双重递减的“计数器”,以避免使用 length/2
。 - lurkerlength(L) == length(L1)
这不是在Prolog中比较列表长度的方法。它比较''项''length(L)
和length(L1)
而没有进行解释,即没有调用任何谓词。要比较长度,请执行以下操作:
length(L, N), length(L1, N)
length(L,Q), length(L1,W), Q =:= W.
这种写法,像larsmans所示,只需使用length(L,N), length(L1,N)
就足够了。 - lurker我喜欢Sergey的解决方案,因为它既优雅又简单(+1)。这里有另一种方法,它在一些进一步的效率方面不太优雅,因为它修剪了查询append
的情况。如果A
或B
中任意一个是ground,则让它们的长度驱动过程。否则,我们让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
| ?-
等等。
div(L, A, B) :-
append(A, B, L),
length(A, O),
length(B, N),
((O-1)=:=N;(O+1)=:=N;O=:=N),
!.
就是这样,可以处理奇数长度的字符串 :)
这只是一个简单的,
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).
length/2
问题,您的解决方案仍然似乎尝试构建前半部分列表,但它没有任何代码来处理后半部分。您可能需要一个辅助谓词来处理长度计数器。或者,您可以考虑使用append/3
。对于div(L, X, Y)
,请查看append(X, Y, L)
并约束X
或Y
的长度。 - lurker