我需要定义除法,以便列表[1,2,3,4,5]
分为:
a = [1,2,3}
b = [4,5]
我收到的错误是"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))
).
答案 0 :(得分: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).
几乎所有最近的Prolog都预先定义了 length/2
和append/3
。
这是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]
答案 1 :(得分: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).
如果您不介意哪些元素进入子列表,只要它们具有相似的长度(如Konstantin Weitz帖子中的解决方案),那么您可以使用:
divide([], [], []).
divide([H|T], [H|A], B) :- divide(T, B, A).
答案 2 :(得分:4)
append是一个预定义的谓词,因此可能是问题所在:http://en.wikibooks.org/wiki/Prolog/Lists#The_append_predicate
你也从未在lengthIs中定义'N' - 你需要将空列表设置为0,而不是N / 可能还有尺寸功能
下划线告诉Prolog我们不关心谓词定义中的那一点。
这样的事情应该有效
divide(L1,L2,L3):- append(L2,L3,L1),
samesize(L2,L3).
divide(L1,L2,L3):- append(L2,L3,L1),
onebigger(L2,L3).
samesize(A,B):- size(A,N),
size(B,N).
onebigger(A,[_|T]):- size(A,N),
size(T,N).
size([],0).
size([H|T],N):- size(T,M+1).
答案 3 :(得分:2)
无需检查尺码。就这样做:
div([],[],[]).
div([A],[A],[]).
div([A,B|T],[A|X],[B|Y]) :- div(T,X,Y).
答案 4 :(得分:2)
此代码(lengthIs(L2, M) < lengthIs(L1,N)/2 -> ...
)的效果肯定不是您所期望的:它不会比较数字,而是比较术语。你应该这样写:
lengthIs(L2, M), lengthIs(L1, N), M < N/2 -> ...
另一个错误的错误:lengthIs / 2的第一个句子应该是
lengthIs([],0).
答案 5 :(得分:0)
另一个答案,
虽然使用Backtracking很多,但性能不是很好。
假定append
和length
是预定义的:
divide(A,B,C):-
append(B,C,A),
length(B,B_Length),
length(C,C_Length),
(B_Length = C_Length;
B_Length =:= C_Length +1).
哦,对不起,只是看到这是对菲利普怀特豪斯答案的一种改述。
答案 6 :(得分:0)
这就是我做的。几乎没有内置插件:
split_list_in_half( Xs , H , T ) :-
list_length( X , L ) ,
LL = L - (L // 2) ,
take_first( Xs , LL , H , T ) ,
.
list_length( L , N ) :-
list_length( L , 0 , N )
.
list_length( [] , N , N ).
list_length( [X|Xs] , T , N ) :-
T1 is T+1 ,
list_length( Xs , T1 , N )
.
take_first( Xs , N , Pfx , Sfx ) :-
take_first( Xs , N , [] , P1 , Sfx ) ,
reverse( P1 , Pfx )
.
take_first( [] , _ , H , H , [] ).
take_first( [X|Xs] , 0 , H , H , [X|Xs] ).
take_first( [X|Xs] , N , H1 , H , T ) :-
N > 0 ,
N1 = N-1 ,
take_first( Xs , N1 , [X|H1] , H , T )
.