2011-11-18 36 views
8

tôi cần phải xác định phân chia để Danh sách [1,2,3,4,5] chia thành:Chia một danh sách trong nửa

a = [1,2,3} 

b = [4,5] 

tôi nhận được một lỗi mà nói "Arguments are not sufficiently instantiated", và tôi không biết đủ về ngôn ngữ để tìm ra vấn đề của tôi là gì, hoặc nếu thiết kế của tôi thậm chí còn đúng. Mọi hướng dẫn sẽ được đánh giá cao.

Vì vậy, đây là những gì tôi có cho đến nay:

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)) 
    ). 
+2

Giải pháp bạn đã chọn làm câu trả lời không thành công cho 'div ([1,2,3,4,5], [1,2,3], [4,5]). ' – false

Trả lời

8

Hãy cung cấp cho các vị một tên quan hệ hơn: 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). 

length/2append/3 được xác định trước trong thực tế tất cả Prologs gần đây.

Đây là 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

+1 để sử dụng' độ dài/2' để tạo danh sách kết quả xương. –

4

append là một vị được xác định trước, do đó có thể là vấn đề: http://en.wikibooks.org/wiki/Prolog/Lists#The_append_predicate

Bạn cũng không bao giờ định nghĩa 'N' trong lengthIs - bạn cần đặt danh sách trống là 0, không phải N/ Có khả năng cũng có chức năng kích thước

Dấu gạch dưới nói với Prolog chúng tôi không quan tâm đến bit đó trong định nghĩa vị ngữ đó.

Something như thế này nên làm việc

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). 
2

Không cần phải kiểm tra kích cỡ. Chỉ cần nó như thế này:

div([],[],[]). 
div([A],[A],[]). 
div([A,B|T],[A|X],[B|Y]) :- div(T,X,Y). 
+2

lưu ý rằng các giải pháp này không thực sự phù hợp với đặc điểm kỹ thuật OP vì nó có 'div ([1,2,3,4,5], [1, 3, 5], [2, 4])' thay vì 'div ([1, 2, 3, 4, 5], [1, 2, 3], [4, 5]) '. – salva

+2

@KonstantinWeitz: điều này chia '[1,2,3,4,5]' thành '[1,3,5]' và '[2,4]'. Nó chia nó thành 2 danh sách với độ dài chính xác, nhưng không đúng * nội dung *. –

2

Chắc chắn ảnh hưởng của mã này (lengthIs(L2, M) < lengthIs(L1,N)/2 -> ...) không phải là những gì bạn mong đợi: nó không so sánh con số, nhưng thuật ngữ này. Bạn nên viết nó theo cách này:

lengthIs(L2, M), lengthIs(L1, N), M < N/2 -> ... 

Một typo như sai lầm: mệnh đề đầu tiên của lengthIs/2 nên đọc

lengthIs([],0). 
5

Đây là giải pháp hiệu quả nhất phù hợp với đặc điểm kỹ thuật của bạn cho hầu hết các trường 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). 

Nếu bạn không nhớ mà các yếu tố đi vào các danh sách con như xa như họ đang có chiều dài tương tự (như trong các giải pháp từ Konstantin Weitz bưu điện), sau đó bạn ca n sử dụng:

divide([], [], []). 
divide([H|T], [H|A], B) :- divide(T, B, A). 
+1

Giải pháp của bạn chấm dứt nếu độ dài của danh sách thứ nhất hoặc danh sách thứ hai được biết. Vì vậy, 'chia (L, A, B) terminates_if ràng buộc (L); ràng buộc (A) .' Nhưng nó vẫn không chấm dứt cho 'phân chia (L, A, []). 'Hai câu trả lời được mong đợi ở đây! 'L = [], A = []; L = [X], A = [X] ' – false

+0

có, vị từ đó được dự kiến ​​sẽ được sử dụng như' phân chia (+, -, -) '. – salva

+1

Bạn tốt hơn '+, -, -' rồi! Có 'phân chia (L, [a], H)' và thậm chí 'phân chia ([a | _], [b | _], _)' độc đáo chấm dứt. – false

0

câu trả lời khác, sử dụng được backtracking rất nhiều, không phải là rất performant, mặc dù. appendlength được giả định được xác định trước:

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). 

Ồ, xin lỗi, chỉ là ta đã thấy rằng đây là loại một rephrasing của câu trả lời từ Philip Whitehouse.

0

Đây là cách tôi đã làm.Hầu như không được tích hợp sẵn:

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) 
    . 
Các vấn đề liên quan