If we can generate all possible valid lengths for each list, then we can generate these lengths and then read that out into our result using list slicing.
More specifically, we need to generate all possible permutations of positive integers such that they sum to the length of the list to partition.
A minor variant of this question happened to be asked on StackOverflow in 2011. (This variant merely required that all the numbers be non-negative, rather than strictly positive.) Using the code from this answer with minor modifications, we can generate the desired permutations and then read them off into our final result:
def sums(length, total_sum):
if total_sum == 0:
return
if length == 1:
yield (total_sum,)
else:
for value in range(1, total_sum + 1):
for permutation in sums(length - 1, total_sum - value):
yield (value,) + permutation
mas = [1, 2, 3, 4, 5]
K = 3
results = []
for lengths in sums(K, len(mas)):
slices = []
start = 0
for slice_length in lengths:
slices.append(mas[start:start+slice_length])
start += slice_length
results.append(slices)
print(results)
You can make this code more concise by generating the start index using accumulate()
and chain()
from itertools
:
mas = [1, 2, 3, 4, 5]
K = 3
results = []
for lengths in sums(K, len(mas)):
slices = []
for start, slice_length in zip(chain([0], accumulate(lengths)), lengths):
slices.append(mas[start:start+slice_length])
results.append(slices)
These output:
[
[[1], [2], [3, 4, 5]],
[[1], [2, 3], [4, 5]],
[[1], [2, 3, 4], [5]],
[[1, 2], [3], [4, 5]],
[[1, 2], [3, 4], [5]],
[[1, 2, 3], [4], [5]]
]