For example, wanting a sum of 3 into 4 spaces would be:
3 0 0 0,
0 3 0 0,
0 0 3 0,
0 0 0 3,
0 1 1 1,
1 0 1 1,
1 1 0 1,
1 1 1 0,
2 1 0 0,
...
or sum of 3 into 2 spaces would be:
2 1
1 2
0 3
3 0
For example, wanting a sum of 3 into 4 spaces would be:
3 0 0 0,
0 3 0 0,
0 0 3 0,
0 0 0 3,
0 1 1 1,
1 0 1 1,
1 1 0 1,
1 1 1 0,
2 1 0 0,
...
or sum of 3 into 2 spaces would be:
2 1
1 2
0 3
3 0
The sequences you are looking for are called compositions.
Finding a composition of a number n is equivalent to selecting indices in an interval from 0 to n. You recover the composition by getting the distance between consecutive selected indices.
Given the number n = 3, we want a composition of length 4.
The first two indices must be 0 and 3 since this is our range. We then select three more indices in the interval [0, 1, 2, 3] to produce exactly 4 gaps.
[0, 1, 2, 3]
^ ^ ^
^ ^
We thus selected 0, 2, 2, 3, 3. We recover the composition by getting the distance between consecutive indices. That is [2, 0, 1, 0].
This corresponds to taking a combination with replacement of numbers from 0 to 3. We can thus use itertools.combinations_with_replacement
and translate each such combination into the corresponding composition.
def compositions(sum_, n):
for indices in combinations_with_replacement(range(sum_ + 1), n - 1):
yield [b - a for a, b in zip([0, *indices], [*indices, sum_])]
print(*compositions(3, 4))
[0, 0, 0, 3]
[0, 0, 1, 2]
[0, 0, 2, 1]
[0, 0, 3, 0]
[0, 1, 0, 2]
[0, 1, 1, 1]
[0, 1, 2, 0]
[0, 2, 0, 1]
[0, 2, 1, 0]
[0, 3, 0, 0]
[1, 0, 0, 2]
[1, 0, 1, 1]
[1, 0, 2, 0]
[1, 1, 0, 1]
[1, 1, 1, 0]
[1, 2, 0, 0]
[2, 0, 0, 1]
[2, 0, 1, 0]
[2, 1, 0, 0]
[3, 0, 0, 0]
Using itertools.product
and filter
create all the possibilities and then filter the ones whose sum is 3
from itertools import product
lst = [0, 1, 2, 3]
print(list(filter(lambda x: sum(x) == 3, product(lst, repeat = 4))))
print(list(filter(lambda x: sum(x) == 3, product(lst, repeat = 2))))