(Python) I would like to generate all possible combinations with length 9 out of a sorted list list with 150 numbers. However, that\'s not very efficient, so I want to have
Here's a solution using a recursive generator function: the function combinations_max_diff takes a list of numbers nums, a number of elements k, and a maximum difference max_diff.
The helper function does all of the work; it takes a partial combination comb, a number of remaining elements r, a minimum list index i for the next element to be chosen in the combination, and a max_next which controls the maximum size of that next element.
def combinations_max_diff(nums, k, max_diff):
# input list must be sorted
nums = sorted(nums)
n = len(nums)
def helper(comb, r, i, max_next):
if r == 0:
yield comb
else:
for ii in range(i, n - r + 1):
v = nums[ii]
if v > max_next: break
comb_v = comb + (v,)
yield from helper(comb_v, r - 1, ii + 1, v + max_diff)
return helper((), k, 0, nums[-1])
Example usage:
>>> nums = [1, 2, 3, 4, 5, 6, 7]
>>> for c in combinations_max_diff(nums, 3, 2):
... print(c)
...
(1, 2, 3)
(1, 2, 4)
(1, 3, 4)
(1, 3, 5)
(2, 3, 4)
(2, 3, 5)
(2, 4, 5)
(2, 4, 6)
(3, 4, 5)
(3, 4, 6)
(3, 5, 6)
(3, 5, 7)
(4, 5, 6)
(4, 5, 7)
(4, 6, 7)
(5, 6, 7)
The question asks about efficiency, so here's some idea about that:
>>> import random, timeit
>>> nums = sorted(random.randrange(0, 5000) for _ in range(150))
>>> len(list(combinations_max_diff(nums, 9, 150)))
16932905
>>> timeit.timeit(lambda: list(combinations_max_diff(nums, 9, 150)), number=1)
15.906288493999455
So, about 16 seconds to generate about 17 million combinations, or a little under one microsecond per combination on my machine.