prolog: subsets of length k
in class we went over the subset_of/2 predicate that my teacher gave as follows:
subset_of([],[]).
subset_of([X|Xs],Zs):-subset_of(Xs,Ys),maybe_add(X,Ys,Zs).
maybe_add(_,Ys,Ys).
maybe_add(X,Ys,[X|Ys]).
subsets_of(Xs,Xss):-findall(Ys,subset_of(Xs,Ys),Xss).
He then asked us to change it to only give the subsets of some length K (but not by using length/2, by directly finding a recursive definition). My first attempt was to split up the subset_of call into one that adds the extra element and one that does not (instead of having the maybe_add call) and to keep track of the length of the list that was passed and check at the end, but this did not work as planned at all.
subset_of(K, 0, [],[]).
subset_of(K, Len, [X|Xs],Zs):-
L1 is Len - 1,
subset_of(K, L1, Xs, Zs),
L1 == K.
subset_of(K, Len, [X|Xs],Zs):-
L1 is Len - 1,
subs开发者_运维知识库et_of(K, L1, Xs,Ys),
do_add(X, Ys, Zs),
Len == K.
subsets_of(K,Xs,Xss):-
length(Xs, Len),
findall(Ys,subset_of(K, Len, Xs,Ys),Xss).
I am NOT asking for the correct code to solve this, but only a push in the right direction so I can keep trying to figure it out. This is my first time with a declarative languange and I am pretty confused.
If you don't want a direct answer, than I'd say that it can be done much simpler. I've got 3 rules in my solution. However I don't use this additional maybe_add
formula or anything that resambles it. If you really need it, it can be used and it takes 5 arguments then - 3 input arguments and 2 output arguments. This reduces the number of rules for subset_of
to only 2, just as in the original solution. They are quite similar after all.
Also watch out for repetitions. I think subset_of(0, _, [])
as suggested in other answer may be a way that leads to repetitions. However there might be a correct solution that incorporates it, I'm not sure that there isn't.
Think of it as a proof of correctness. Say you wanted to prove recursively that one set is a K-element subset of another. How would you go about it. Look at the implications that you used. How can you turn them into Prolog rules?
Not using maybe_add
seems like a good idea. However, you don't need two extra arguments: one will do. Your base clause would be
subset_of(0, _, []).
i.e., the empty set is a zero-element subset of anything. Of the two recursive clauses, one would look for K-1
-element subsets, the other for K
-sized subsets.
精彩评论