You can use a recursive generator function:
def combos(nums, buckets, c = []):
if len(c) == buckets:
yield c
else:
if len(c) + len(nums) < buckets:
yield from combos(nums, buckets, c+[None])
for i, a in enumerate(nums):
yield from combos(nums[:i]+nums[i+1:], buckets, c+[a])
print(list(combos([1, 2, 3, 4, 5], 4)))
print(list(combos([1, 2, 3], 4)))
Output:
[[1, 2, 3, 4], [1, 2, 3, 5], [1, 2, 4, 3], [1, 2, 4, 5], [1, 2, 5, 3], [1, 2, 5, 4], [1, 3, 2, 4], [1, 3, 2, 5], [1, 3, 4, 2], [1, 3, 4, 5], [1, 3, 5, 2], [1, 3, 5, 4], [1, 4, 2, 3], [1, 4, 2, 5], [1, 4, 3, 2], [1, 4, 3, 5], [1, 4, 5, 2], [1, 4, 5, 3], [1, 5, 2, 3], [1, 5, 2, 4], [1, 5, 3, 2], [1, 5, 3, 4], [1, 5, 4, 2], [1, 5, 4, 3], [2, 1, 3, 4], [2, 1, 3, 5], [2, 1, 4, 3], [2, 1, 4, 5], [2, 1, 5, 3], [2, 1, 5, 4], [2, 3, 1, 4], [2, 3, 1, 5], [2, 3, 4, 1], [2, 3, 4, 5], [2, 3, 5, 1], [2, 3, 5, 4], [2, 4, 1, 3], [2, 4, 1, 5], [2, 4, 3, 1], [2, 4, 3, 5], [2, 4, 5, 1], [2, 4, 5, 3], [2, 5, 1, 3], [2, 5, 1, 4], [2, 5, 3, 1], [2, 5, 3, 4], [2, 5, 4, 1], [2, 5, 4, 3], [3, 1, 2, 4], [3, 1, 2, 5], [3, 1, 4, 2], [3, 1, 4, 5], [3, 1, 5, 2], [3, 1, 5, 4], [3, 2, 1, 4], [3, 2, 1, 5], [3, 2, 4, 1], [3, 2, 4, 5], [3, 2, 5, 1], [3, 2, 5, 4], [3, 4, 1, 2], [3, 4, 1, 5], [3, 4, 2, 1], [3, 4, 2, 5], [3, 4, 5, 1], [3, 4, 5, 2], [3, 5, 1, 2], [3, 5, 1, 4], [3, 5, 2, 1], [3, 5, 2, 4], [3, 5, 4, 1], [3, 5, 4, 2], [4, 1, 2, 3], [4, 1, 2, 5], [4, 1, 3, 2], [4, 1, 3, 5], [4, 1, 5, 2], [4, 1, 5, 3], [4, 2, 1, 3], [4, 2, 1, 5], [4, 2, 3, 1], [4, 2, 3, 5], [4, 2, 5, 1], [4, 2, 5, 3], [4, 3, 1, 2], [4, 3, 1, 5], [4, 3, 2, 1], [4, 3, 2, 5], [4, 3, 5, 1], [4, 3, 5, 2], [4, 5, 1, 2], [4, 5, 1, 3], [4, 5, 2, 1], [4, 5, 2, 3], [4, 5, 3, 1], [4, 5, 3, 2], [5, 1, 2, 3], [5, 1, 2, 4], [5, 1, 3, 2], [5, 1, 3, 4], [5, 1, 4, 2], [5, 1, 4, 3], [5, 2, 1, 3], [5, 2, 1, 4], [5, 2, 3, 1], [5, 2, 3, 4], [5, 2, 4, 1], [5, 2, 4, 3], [5, 3, 1, 2], [5, 3, 1, 4], [5, 3, 2, 1], [5, 3, 2, 4], [5, 3, 4, 1], [5, 3, 4, 2], [5, 4, 1, 2], [5, 4, 1, 3], [5, 4, 2, 1], [5, 4, 2, 3], [5, 4, 3, 1], [5, 4, 3, 2]]
[[None, 1, 2, 3], [None, 1, 3, 2], [None, 2, 1, 3], [None, 2, 3, 1], [None, 3, 1, 2], [None, 3, 2, 1], [1, None, 2, 3], [1, None, 3, 2], [1, 2, None, 3], [1, 2, 3, None], [1, 3, None, 2], [1, 3, 2, None], [2, None, 1, 3], [2, None, 3, 1], [2, 1, None, 3], [2, 1, 3, None], [2, 3, None, 1], [2, 3, 1, None], [3, None, 1, 2], [3, None, 2, 1], [3, 1, None, 2], [3, 1, 2, None], [3, 2, None, 1], [3, 2, 1, None]]
At each recursive call, if a combination has not yet been formed, the code does two things:
- Checks if the specified number of buckets is greater than the input number list. If so, then the output is padded with
None.
- The remaining number list is iterated over, and each iteration value is added to the running result, and the recursion proceeds.