将列表分成两半

bdm*_*yer 8 list prolog

我需要定义除法,以便List [1,2,3,4,5]分为:

a = [1,2,3}

b = [4,5]
Run Code Online (Sandbox Code Playgroud)

我收到的错误是"Arguments are not sufficiently instantiated",我对语言知之甚少,无法弄清楚我的问题是什么,或者我的设计是否正确.任何指导将不胜感激.

所以这就是我到目前为止所拥有的:

append([],L2,L2).
append([H|T],L2,[H|L3]) :- append(T,L2,L3).

lengthIs([],N).
lengthIs([H|T],N) :- lengthIs(T,M), N is M+1.

divide([],[],[]).
divide([H|T],L2,L3) :-
   (  lengthIs(L2, M) < lengthIs(L1,N)/2
   -> divide(T, append(L2, H, X), L3)
   ;  divide(T, L2, append(L3,H,Y))
   ).
Run Code Online (Sandbox Code Playgroud)

fal*_*lse 8

让我们给谓词一个更多的关系名称: list_half_half/3

list_half_half(Xs, Ys, Zs) :-
   length(Xs, N),
   H is N - N // 2,
   length(Ys, H),
   append(Ys, Zs, Xs).
Run Code Online (Sandbox Code Playgroud)

length/2并且append/3几乎在所有最近的Prolog中预先定义.

这是GNU Prolog:

| ?- append(L,_,[a,b,c,d]), list_half_half(L,H1,H2).

H1 = []
H2 = []
L = [] ? ;

H1 = [a]
H2 = []
L = [a] ? ;

H1 = [a]
H2 = [b]
L = [a,b] ? ;

H1 = [a,b]
H2 = [c]
L = [a,b,c] ? ;

H1 = [a,b]
H2 = [c,d]
L = [a,b,c,d]
Run Code Online (Sandbox Code Playgroud)


sal*_*lva 5

这是符合大多数Prolog实现规范的最有效解决方案:

divide(L, A, B) :-
    divide1(L, L, A, B).

divide1([], L, [], L).
divide1([_|T], [H|L], [H|A], B) :-
    divide2(T, L, A, B).

divide2([], L, [], L).
divide2([_|T], L, A, B) :-
    divide1(T, L, A, B).
Run Code Online (Sandbox Code Playgroud)

如果您不介意哪些元素进入子列表,只要它们具有相似的长度(如Konstantin Weitz帖子中的解决方案),那么您可以使用:

divide([], [], []).
divide([H|T], [H|A], B) :- divide(T, B, A).
Run Code Online (Sandbox Code Playgroud)