Reputation: 173
I need to generate all the combinations with length k
from a list of length n
, and I must do it using recursion.
For Example:
INPUT: choose_sets([1,2,3,4],3)
OUTPUT: [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
INPUT: choose_sets([1,2,3,4],2)
OUTPUT: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
I'm stuck implementing this in code, so I would be happy for some help. This is my code so far (I'm missing something just don't know what):
def choose_sets(lst,k):
if k == len(lst):
return lst
if k == 0:
return []
if k > len(lst):
return []
sets=[]
sub_lst=lst[:]
sub_lst.remove(sub_lst[0])
a= choose_sets(sub_lst,k-1)
for i in a:
i.append(lst[0])
sets.append(a)
b= choose_sets(sub_lst,k)
sets.append(b)
return sets
Upvotes: 4
Views: 7972
Reputation: 51705
You can get solution from Generator for permutations, combinations, selections of a sequence (Python recipe)
def xuniqueCombinations(items, n):
if n==0: yield []
else:
for i in xrange(len(items)):
for cc in xuniqueCombinations(items[i+1:],n-1):
yield [items[i]]+cc
>>> def xuniqueCombinations(items, n):
... if n==0: yield []
... else:
... for i in xrange(len(items)):
... for cc in xuniqueCombinations(items[i+1:],n-1):
... yield [items[i]]+cc
...
>>> for x in xuniqueCombinations( [1,2,3,4],2):
... print x
[1, 2]
[1, 3]
[1, 4]
[2, 3]
[2, 4]
[3, 4]
Edited 4 year later (7/12/2015)
To run it on Python3 just change xrange
to range
, Python3's range is Python2's xrange.. Thanks @ederollora to notice me.
Upvotes: 7
Reputation: 183968
You are almost there, just a few minor things. The algorithm is basically correct, but
if k == len(lst):
return lst
This has the wrong type. The return type is not a list of thing, but a list of (list of thing), so that should be
if k == len(lst):
return [lst]
Next,
if k == 0:
return []
Every list has exactly one nonempty sublist, the empty list, so that ought to be
if k == 0:
return [[]]
For the rest,
if k > len(lst):
return []
is completely correct.
sets=[]
sub_lst=lst[:]
sub_lst.remove(sub_lst[0])
That is correct but could be put more succinctly as
sub_lst = lst[1:]
Now, another type mix-up:
a= choose_sets(sub_lst,k-1)
for i in a:
i.append(lst[0])
sets.append(a)
That sets.append(a)
puts a
into one slot of sets
, you want to concatenate the two lists, sets = sets + a
. And if you would like the combinations in the order in which elements appear in the list, instead of i.append(lst[0])
, you should append [lst[0]] + i
to sets
in the loop, but that's a matter of inclination.
b= choose_sets(sub_lst,k)
sets.append(b)
Again, do not append, but concatenate here,
sets = sets + b
Upvotes: 0
Reputation: 7817
basically you need to use the following recursion:
f(k,n) = append_to_each( f(k-1,n-1), n) | f(k,n-1)
def combinations(lst,k):
n = len(lst)
if n == k:
return [set(lst)]
if k == 1:
return [set([lst[i]]) for i in range(n)]
v1 = combinations(lst[:-1], k-1)
v1new = [ i.add(lst[n-1]) for i in v1]
v2 = combinations(lst[:-1], k)
return v1+v2
Upvotes: 0
Reputation: 6073
This is in Java, and I can't guarantee it works 100% properly, but based on quick prototyping seemed to work ok. Hope this helps a bit in any case.
public void choose_sets(int values[], int count) {
int perm[] = new int[count];
choose_sets(values, 0, perm, 0, count);
}
public void choose_sets(int[] values, int valuesIdx, int[] perm,
int permIdx, int count) {
if (permIdx == count) {
// At this point perm -array contains single permutation
// of length ´count´.
} else {
for (int i = valuesIdx; i < values.length; ++i) {
perm[permIdx] = values[i];
choose_sets(values, i + 1, perm, permIdx + 1, count);
}
}
}
Upvotes: 0
Reputation: 5544
Give a look to this solution:
def choose_sets(mylist,length):
mylen = len(mylist)
if length == mylen:
return [mylist]
if length == 1:
return [[i] for i in mylist]
if length > mylen:
return []
ToRet = []
for k in xrange(mylen):
if mylen - k + 1> length :
for j in choose_sets(mylist[k+1:],length-1):
New = [mylist[k]]
New.extend(j)
ToRet.append(New)
return ToRet
print choose_sets([1,2,3,4,5],3)
there are more elegant ways, but this should be ok as homework...
Upvotes: 0