Newbie here.I have this code, that displays all possible sums to reach a certain number. But its complexity is too high and it takes too longe when numbers are too high. How can I refactor this to something more simple?
import itertools
def combos(n):
result = []
for i in range(n,0,-1):
for seq in itertools.combinations_with_replacement(range(1,n+1), i):
if sum(seq) == n:
seq = list(seq)
result.append(seq)
return(result)
combos(4)
output:
[[1,1,1,1],[1,1,2],[1,3],[2,2],[4]]
The recursive version could be like this:
def combinations_max_sum(sum_max, i_max=None):
if sum_max == 0:
return [()]
if not i_max or i_max > sum_max:
i_max = sum_max
combinations = [(i, *right_part)
for i in range(i_max, 0, -1)
for right_part in combinations_max_sum(sum_max-i, i_max=i)]
return combinations
Test:
print(combinations_max_sum(4)) # [(4,), (3, 1), (2, 2), (2, 1, 1), (1, 1, 1, 1)]
print(combinations_max_sum(4, i_max=1)) # [(1, 1, 1, 1)]
print(combinations_max_sum(5))
# [(5,), (4, 1), (3, 2), (3, 1, 1), (2, 2, 1), (2, 1, 1, 1), (1, 1, 1, 1, 1)]
The idea to decompose the problem: a set of combinations can be written as a number concatenated with all the combinations for which the sum is n
minus that first number.
A simpler code without dealing with repetition could be like this:
def combinations_with_repetition(n):
if n == 0:
return [()]
combinations = [(i, *right_part) # concatenation
for i in range(1, n+1) # for all possible first number
for right_part in combinations_with_repetition(n-i)]
# ^ all possible combinations
# given the first number i
return combinations
which gives:
combinations_with_repetition(3)
# [(1, 2), (1, 1, 1), (2, 1), (3,)]
(1, 2)
and (2, 1)
are similar, to prevent this a i_max
argument is added (see the first function). The idea here is to go always in descending order. A number on the right is always equal or smaller than a number on the left. This maximum number is passed as an argument, and the loop start with it instead of the total sum asked.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.