Bài tập 09 trên trang này http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/ yêu cầu tạo một biến vị ngữ mà gói các phần tử lặp lại vào các danh sách con.`var (A)` và thứ tự thực hiện
Một giải pháp đơn giản là đơn giản
pack([], []).
pack([H|T], [I|U]) :-
split(H, T, I, P),
pack(P, U).
nơi chia được split(Head, Tail, HeadGroup, Rest)
được định nghĩa là
split(A, [], [A], []).
split(A, [B|T], [A], [B|T]) :- A \= B.
split(A, [A|T], [A|U], B) :- split(A, T, U, B).
mà hoạt động tốt và có khá nhiều phù hợp với giải pháp dụ được cung cấp trên trang web nêu trên .
Trường hợp giải pháp này không thành công là các truy vấn như pack(X, [[a], [b, b]]).
. Sự tương ứng giữa hai bộ giải pháp là tính từ (đối với mỗi A
trong pack(A, B)
có một và chỉ một B
), do đó phải có giải pháp tốt hơn.
Một cách để giải quyết nó là để thay đổi thứ tự đánh giá, giúp prolog để chọn chi nhánh không vô hạn tùy thuộc vào loại đối số như sau
pack([], []).
pack(A, B) :-
(var(A) ->
A = [H|T],
B = [I|U],
pack(P, U),
split(H, T, I, P)
; A = [H|T],
B = [I|U],
split(H, T, I, P),
pack(P, U)
).
Hai câu hỏi về vấn đề này.
Thứ nhất, điều này là không thể tin được xấu xí, vậy có cách nào tốt hơn để chọn thứ tự các quy tắc tùy thuộc vào loại đối số không?
Thứ hai, có lẽ là câu hỏi phức tạp hơn nhiều, có cách nào để viết lại giải pháp mà không cần var(A)
và nếu không phải lý do?
Thiên tài thuần khiết! Với 'dif' nó bây giờ thậm chí có thể giải quyết những thứ điên rồ như' gói (A, [X, [b]]). – vasily
Gonna xem lại tất cả các giải pháp trước của tôi. – vasily
Vâng, đúng thế. 'dif/2' đã có sẵn ngay cả trong hệ thống Prolog đầu tiên, sau đó bởi và lớn bị bỏ qua bởi những người triển khai, và bây giờ ngày càng trở nên phổ biến trong việc triển khai một lần nữa. Dù sao đi nữa, lý luận về mọi hướng là một trong những điểm thu hút chính của lập trình quan hệ, vì vậy hãy sử dụng 'dif/2' để diễn tả sự bất bình đẳng trong một cách âm thanh và tổng quát. – mat