2015-10-23 18 views
5

Tôi đang cố gắng tạo mã để tạo tất cả các tập hợp con của một tập hợp theo thứ tự. Đó là, gọi subset([1,2,3], X) nên tạoĐộ dài của các tập hợp con đã đặt hàng?

X = []; 
X = [1]; 
X = [2]; 
X = [3]; 
X = [1,2]; 
X = [1,3]; 
X = [2,3]; 
X = [1,2,3]. 

Trình tự nội bộ không phải là tất cả những gì quan trọng, chỉ là tập con nhỏ nhất được liệt kê đầu tiên (tức là tôi không quan tâm nếu [2,3] đến trước [1 , 2], chỉ có 1, [2] và [3] là trước [2,3]).

-

Tôi đã thử hai cách tiếp cận cho đến nay. Trước tiên, tôi đã cố gắng tự tạo vị ngữ cho mình ...

subset([], []). 
subset(List, []). 
subset(List, [N]) :- 
    member(N, List). 

subset(List, [N|Rest]) :- 
    !, 
    nth0(I, List, N), 
    findall(E, (nth0(J, List, E), J > I), NewList), 
    subset2(NewList, Rest). 

... nhưng nó thậm chí còn không hoạt động như dự định. Thứ hai tôi đã cố gắng làm cho các powerset (sử dụng this subset predicate) và đặt hàng với list_to_ord_set/2, nhưng tôi không thể làm cho nó hoạt động.

Trợ giúp?

Trả lời

1

Tôi đã tìm thấy một giải pháp không tao nhã như vậy ... nó đòi hỏi một vết cắt và một số lệnh nội trú

subset(Xs, Ys) :- 
    length(Xs, L), 
    between(0, L, N), 
    length(Ys, N), 
    assign(Xs, Ys). 

assign(_, []) :- !. 
assign([X|Xs], [X|Ys]) :- 
    assign(Xs, Ys). 
assign([_|Xs], Ys) :- 
    assign(Xs, Ys). 

như ghi nhận của @Fatalize, chúng ta có thể tránh được việc cắt giảm, chỉ cần buộc các danh sách trống trên số đầu tiên trong tổng số 1^khoản:

assign([], []). 
assign([X|Xs], [X|Ys]) :- 
    assign(Xs, Ys). 
assign([_|Xs], Ys) :- 
    assign(Xs, Ys). 

tôi tránh để hoán đổi 2^3^khoản, do đó thứ tự 'tự nhiên' vẫn độc đáo bảo quản

+2

Bạn không cần cắt nếu bạn sử dụng 'assign ([], []).' Thay vì quy tắc đầu tiên của bạn? Nếu bạn muốn loại bỏ các đánh giá cuối cùng mà kết quả đầu ra 'false' cho một số lý do bạn chỉ có thể trao đổi thứ tự của các quy tắc' assign' thứ hai và thứ ba. Nó thay đổi thứ tự nhưng vẫn hợp lệ theo những gì OP muốn. – Fatalize

+0

@Fatalize: yêu cầu cắt để tránh các giải pháp trùng lặp và biến anon để chấp nhận danh sách con của Xs – CapelliC

+1

Tôi không nhận được. Tôi có được kết quả chính xác tương tự với những thay đổi đó. Chăm sóc để cung cấp một ví dụ yêu cầu cắt và biến vô danh? – Fatalize

3

Luôn cũng xem xét sử dụng DCG notation whe n mô tả danh sách.

Ví dụ: truy vấn

list_sublist(Ls0, Ls) :- 
     same_length(Ls0, Ls1), 
     append(Ls, _, Ls1), 
     phrase(sublist(Ls0), Ls). 

sublist([])  --> []. 
sublist([L|Ls]) --> ([] ; [L]), sublist(Ls). 

mẫu:

?- list_sublist([a,b,c], Ls). 
Ls = [] ; 
Ls = [c] ; 
Ls = [b] ; 
Ls = [a] ; 
Ls = [b, c] ; 
Ls = [a, c] ; 
Ls = [a, b] ; 
Ls = [a, b, c] ; 
false. 

Một ví dụ khác: trường hợp

?- list_sublist(Ls, [b,c]). 
Ls = [b, c] ; 
Ls = [_G511, b, c] ; 
Ls = [b, _G514, c] ; 
Ls = [b, c, _G517] ; 
etc. 

chung nhất:

?- list_sublist(Xs, Ys). 
Xs = Ys, Ys = [] ; 
Xs = [_G513], 
Ys = [] ; 
Xs = Ys, Ys = [_G513] 
Xs = [_G513, _G516], 
Ys = [] ; 
etc. 
+2

s (X): Tôi thực sự khai thác 'danh sách con // 1'. Làm thế nào để viết '([] | [L])' thay vì '([]; [L])'? – repeat

+1

Tôi nói chung * rất thích * sử dụng '|' trong DCGs, +1! Có lẽ nó là dễ đọc hơn mặc dù khi biến không chính xác được gọi là 'L', phải không? So sánh '[] | [L] 'hoặc thậm chí ít có thể đọc được' [] | [L] 'với' []; [L] 'hoặc' []; [L] '.Vì tôi thực sự muốn sử dụng 'L' trong trường hợp này, tôi thấy'; 'hơi dễ đọc hơn trong trường hợp cụ thể này. Tôi chắc chắn sẽ sử dụng '|' trong các trường hợp như '[] | [_] '. – mat

+1

Có bất kỳ dữ liệu nào về sự giống nhau về hình ảnh của các ký tự ASCII trong điều kiện đọc khó không? Sth như tệp thuật ngữ "tuyệt vời rune", nhưng không phải cho chữ hoa so với chữ thường, nhưng chữ hoa và chữ hoa. Tôi đoán "L" là xấu khi có thể có bất kỳ "[| I_17" xung quanh (cộng thêm một số nếu chúng ta xem xét sử dụng * in nghiêng * để nhấn mạnh sth) ... – repeat

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