This is a Python program that finds all possible ways a positive integer num
can be expressed a sum of a number of integers between 1 and lim
(including both ends).
There is no limit on the number of integers, duplicates are allowed, same elements in different order is considered different.
The output is a nested dictionary. Each key is a possible integer, each key in the nested dictionary is a possible integer in the series formed by the keys of the parent dictionaries in the previous levels that allows or makes the series sum to num
.
From any last level keys, through the keys in the parent dictionaries, to the first level parent key, the sum of such a series is always num
.
The Code
def partition_tree(num: int, lim: int) -> dict:
"""take a positive integer `num` and a positive integer `lim`,
calculate all possible ways integer `num` can be expressed as,
a summation of integers between 1 and `lim`, returns a tree"""
d = dict()
if any(not isinstance(i, int) for i in (num, lim)):
raise TypeError('The parameters of this function should be `int`s')
if any(i <= 0 for i in (num, lim)):
raise ValueError('The parameters should be both greater than 0')
def worker(num: int, lim: int, dic: dict) -> None:
for i in range(1, lim+1):
n = num - i
if n:
dic.setdefault(i, dict())
worker(n, lim, dic[i])
else:
dic.update({i: 0})
break
worker(num, lim, d)
return d
Example output:
def partition_tree(num: int, lim: int) -> dict:
"""take a positive integer `num` and a positive integer `lim`,
calculate all possible ways integer `num` can be expressed as,
a summation of integers between 1 and `lim`, returns a tree"""
d = dict()
if any(not isinstance(i, int) for i in (num, lim)):
raise TypeError('The parameters of this function should be `int`s')
if any(i <= 0 for i in (num, lim)):
raise ValueError('The parameters should be both greater than 0')
def worker(num: int, lim: int, dic: dict) -> None:
for i in range(1, lim+1):
n = num - i
if n:
dic.setdefault(i, dict())
worker(n, lim, dic[i])
else:
dic.update({i: 0})
break
worker(num, lim, d)
return d
import json
print(json.dumps(partition_tree(6, 3), indent=4))
Output:
{
"1": {
"1": {
"1": {
"1": {
"1": {
"1": 0
},
"2": 0
},
"2": {
"1": 0
},
"3": 0
},
"2": {
"1": {
"1": 0
},
"2": 0
},
"3": {
"1": 0
}
},
"2": {
"1": {
"1": {
"1": 0
},
"2": 0
},
"2": {
"1": 0
},
"3": 0
},
"3": {
"1": {
"1": 0
},
"2": 0
}
},
"2": {
"1": {
"1": {
"1": {
"1": 0
},
"2": 0
},
"2": {
"1": 0
},
"3": 0
},
"2": {
"1": {
"1": 0
},
"2": 0
},
"3": {
"1": 0
}
},
"3": {
"1": {
"1": {
"1": 0
},
"2": 0
},
"2": {
"1": 0
},
"3": 0
}
}
I came up with this in under 2 minutes and made it work in one try. I made this for use in my project to generate pseudowords, more specifically to calculate all possible ways a given word length num
can be achieved using chunks of lengths 1 to lim
.
How is the performance, coding style and memory consumption of my code (try partition_tree(18, 6)
, something like this can be in common use)? How can it be improved?
num
? For completeness, the root can be thought of as having a value of zero; all other nodes have non-zero values; node values don't have to be unique. \$\endgroup\$worker(num, lim, dic)
populates the input dictionarydic
with a tree whose root-to-leaf paths each sum tonum
s.t. each node in the tree has a value,v
,1 <= v <= lim
. \$\endgroup\$