Skip to content

Instantly share code, notes, and snippets.

@VehpuS
Last active April 21, 2024 11:08
Show Gist options
  • Save VehpuS/70bf146768f36f1035d78cdc8729d37f to your computer and use it in GitHub Desktop.
Save VehpuS/70bf146768f36f1035d78cdc8729d37f to your computer and use it in GitHub Desktop.
def partition (count, total, steps=1, minimum=0, maximum=None, sum_total=True):
'''
@summary:
Given a number "total" and number of parts to split it to "count", return a count-length tuple made of numbers that sum up to "total".
Steps defines in what increments to increase each "bin", starting with 0 or minimum sized bins to bins of size total or maximum.
If sum total is True - only partitions summing to total will return, otherwise, partitions with lower sums will be returned as well.
@param count:
How many bins to split total into.
@param total:
The total size to split into bins.
@param steps:
In what increments to increase the size of the bins.
i.e. if minimum = 1 and steps = 2, bin sizes will be 1, 3, 5,...
@param minimum:
The minimum size of each bin.
@param maximum:
The maximum size of each bin. If not passed, it will default to the total.
@param sum_total:
If True, only partitions that sum to total will return, otherwise any partitions whose sum is lower than total will be returned.
@notes:
Based on https://stackoverflow.com/questions/41837444/how-to-find-all-ways-to-obtain-an-integer-n-as-the-sum-of-m-integers-without-or
'''
start = minimum
maximum = total if (maximum is None or total < maximum) else maximum
if 0 == count:
yield tuple([])
else:
while (start <= total and
start <= maximum and
total <= count * maximum and
total >= count * minimum):
for part in partition(count - 1, total - start, steps, minimum, maximum, sum_total):
res = part + (start,)
if (not sum_total or len(res) != count or total == sum(res)):
yield res
start = start + steps
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment