This is the code I came up with:
def combinations(input):
ret = ['']
for i in range(len(input)):
ret.extend([prefix+input[i] for prefix in ret])
return ret
This algorithm is O(2^n) time, but can space be reduced? I heard using yield
might work, but having trouble thinking through how to implement with yield
. Please don't use the built in combination function -- I would like to see how it's implemented.
Your question specifically said you wanted to see what the code would look like, so here is a hand coded example of an O(n) space solution:
def combinations(input_list, acc=''):
if not input_list:
yield acc
return
next_val = input_list[0]
for rest in combinations(input_list[1:], acc):
yield rest
acc += next_val
# In python 3.2, you can use "yield from combinations(input_list[1:], acc)"
for rest in combinations(input_list[1:], acc):
yield rest
Note that the substring arithmetic might be expensive (since it has to copy the string many times), so here is a slightly more efficient version in terms of complexity:
def combinations(input_list, acc='', from_idx=0):
if len(input_list) <= from_idx:
yield acc
return
next_val = input_list[from_idx]
for rest in combinations(input_list, acc, from_idx + 1):
yield rest
acc += next_val
# In python 3.2, you can use "yield from combinations(input_list[1:], acc)"
for rest in combinations(input_list, acc, from_idx + 1):
yield rest
I'm not using Python 3.2, but if you were you could write it like this:
def combinations(input_list, acc='', from_idx=0):
if len(input_list) <= from_idx:
yield acc
return
next_val = input_list[from_idx]
yield from combinations(input_list, acc, from_idx + 1)
acc += next_val
yield from combinations(input_list, acc, from_idx + 1)
I should also note that this is purely academic since itertools.combinations
does a fine job and works for a wider array of inputs (including generator expressions).
You can use yield
in your code like so:
def combinations(input):
ret = ['']
yield ''
for i in range(len(input)):
for prefix in ret:
combination = prefix+input[i]
ret.extend(combination)
yield combination
But it doesn't save you any space.
The itertools.combinations documentation shows a (much) more complicated algorithm that works in constant space - the actual implementation is in C, but claims to be equivalent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With