2013-11-28 13 views
5

Tôi đang cố xóa các mục nhập trùng lặp khỏi danh sách trong phần mở đầu. Vì vậy, một danh sách [a, b, a, c, b, a] sẽ trả về [a, b, c]. Tôi không thể sử dụng bất kỳ chức năng tích hợp nào. Tôi đã tìm kiếm ở đây và tìm thấy mã này.Prolog: Loại bỏ các bản sao

member(X,[X|_]) :- !. 
member(X,[_|T]) :- member(X,T). 
set([],[]). 
set([H|T],[H|Out]) :- not(member(H,T)), set(T,Out). 
set([H|T],Out) :- member(H,T), set(T,Out). 

Nhưng điều đó sẽ đưa danh sách của tôi và trở về [c, b, a] không [a, b, c]

Tôi có loại bỏ mã mà sẽ mất một yếu tố và một danh sách và trả về một danh sách với sự xuất hiện của phần tử đó trong danh sách bị xóa. Vì vậy, tôi đã cố gắng để kết hợp đó vào phương pháp loại bỏ trùng lặp của tôi, nhưng tôi không thực sự hiểu prolog rất tốt vì vậy nó không hoạt động. Về mặt logic, tôi muốn lấy một danh sách phản đối đầu bằng cuộc gọi đệ quy trên danh sách mới trừ đi tất cả các lần xuất hiện của đầu. Đây là những gì mã sẽ giống như trong sml.

fun remv(_,nil) = nil 
| remv(a,x::xs) = if x=a then remv(a,xs) else x::remv(a,xs); 
fun remvdub (nil) = nil 
| remvdub(x::xs) = x::remvdub(remv(x,xs)); 

Vì vậy, đây là những gì tôi đã cố gắng trong prolog

remv(_,[],[]). 
remv(X,[X|T],Ans) :- remv(X,T,Ans). 
remv(X,[H|T],[H|K]) :- remv(X,T,K). 

remvdub([],[]). 
remvdub([H|T],[H|Ans]) :- remvdub(Ans1,Ans), remv(H,T,Ans1). 

tôi đang thiếu gì?

Trả lời

7
% An empty list is a set. 
set([], []). 

% Put the head in the result, 
% remove all occurrences of the head from the tail, 
% make a set out of that. 
set([H|T], [H|T1]) :- 
    remv(H, T, T2), 
    set(T2, T1). 

% Removing anything from an empty list yields an empty list. 
remv(_, [], []). 

% If the head is the element we want to remove, 
% do not keep the head and 
% remove the element from the tail to get the new list. 
remv(X, [X|T], T1) :- remv(X, T, T1). 

% If the head is NOT the element we want to remove, 
% keep the head and 
% remove the element from the tail to get the new tail. 
remv(X, [H|T], [H|T1]) :- 
    X \= H, 
    remv(X, T, T1). 
+0

Cảm ơn SQB chính xác là logic của những gì tôi đang cố gắng làm. Ngay cả khi xem xét mã của bạn, tôi dường như không thể tìm ra nơi tôi đã phạm sai lầm, họ cũng đọc như vậy với tôi. Tuy nhiên, bạn làm việc và tôi bị mắc kẹt trong một vòng infinte. – user3043403

+0

hmm tôi nghĩ rằng tôi đã tìm ra, thứ tự bên trong: - quan trọng vì vậy dòng của tôi. remvdub ([H | T], [H | Ans]): - remvdub (Ans1, Ans), remv (H, T, Ans1). Nên là remvdub ([H | T], [H | Ans]): - remv (H, T, Ans1), remvdub (Ans1, Ans). – user3043403

2

Đoạn mã Prolog mà bạn đã đăng là chính xác về mặt logic. Nếu bạn muốn giữ đầu tiên, như trái ngược với trước, bản sao của từng hạng mục trùng lặp, bạn có thể thay đổi mã của bạn như sau:

member(X,[X|_]) :- !. 
member(X,[_|T]) :- member(X,T). 
set(A,B) :- set(A, B, []). 
set([],[],_). 
set([H|T],[H|Out],Seen) :- not(member(H,Seen)), set(T,Out, [H|Seen]). 
set([H|T],Out, Seen) :- member(H,Seen), set(T,Out,Seen). 

Ý tưởng là để thêm một tham số thứ ba, đại diện cho danh sách các mục mà bạn đã thấy cho đến nay và kiểm tra tư cách thành viên chống lại nó thay vì kiểm tra tư cách thành viên so với danh sách còn lại. Lưu ý rằng set/2 được thêm vào để ẩn đối số thứ ba này khỏi người dùng của vị từ của bạn.

Demo on ideone.

+0

Cảm ơn dasblinkenlight, mà làm việc! Trong tò mò là có một cách để làm những gì tôi đã cố gắng trong khối dưới cùng của mã? Nơi tôi sử dụng mã loại bỏ để cắm vào danh sách nhỏ hơn tiến bộ với đầu và các phần tử trùng lặp của đầu bị xóa? – user3043403

+0

@ user3043403 Tôi không hiểu sml, vì vậy tôi không thể hiểu được mã nguyên mẫu hoạt động. Tuy nhiên, mệnh đề thứ hai của thuộc tính 'remvdub/2' trông rất đáng ngờ, vì có vẻ như nó đang đi vào đệ quy vô hạn. – dasblinkenlight

Các vấn đề liên quan