Reputation: 11
I'm trying to find the most efficient way to find all combinations of numbers that equal a given sum.
For example: Looking to find all 3-number combos whose sum = 3
Desired Output: [0,0,3], [0,3,0], [3,0,0], [1,1,1], [1,2,0], [1,2,0], [2,1,0], [2,0,1]
In terms of application I'm trying to generate lists of all of 3-numbered combinations which equal 100. I tried achieving this by creating a list containing numbers 0 - 100 to be used as an input argument and the following code below:
def weightList():
l=[]
for x in range(0,101):
l.append(x)
return l
def subset_sum(numbers, target, partial=[]):
s = sum(partial)
# check if the partial sum is equals to target
if (s == target)&(len(partial) == LoanCount):
print(partial)
if s >= target:
return # if we reach the number why bother to continue
for i in range(len(numbers)):
n = numbers[i]
remaining = numbers[i+1:]
subset_sum(remaining, target, partial + [n])
o=weightList()
subset_sum(o,100)
The problem is that it takes too long because of the amount of iterations it must perform. I also need to include combinations repeating elements and different order/sequence of elements. This method does not. Can anyone provide a much faster/efficient method for me to obtain my desired out come?
Upvotes: 1
Views: 1278
Reputation: 198
You can also use generator and python itertools like this:
from itertools import product
def comb(nx):
list_gen = (n for n in range(nx+1))
list_ = (list(list_gen))
prod = [seq for seq in product(list_, list_, list_) if sum(seq) == nx]
print(list(prod))
result:
[(0, 0, 3), (0, 1, 2), (0, 2, 1), (0, 3, 0), (1, 0, 2), (1, 1, 1), (1, 2, 0), (2, 0, 1), (2, 1, 0), (3, 0, 0)]
and it can run about 10 us in my machine:
9.53 µs ± 177 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Upvotes: 0
Reputation: 17322
you can use a generator to find all possible combinations of 3 numbers that equal a given sum:
def gen_combo_target(s):
for i in range(s + 1):
s2 = s - i
for j in range(s2 + 1):
yield (i, j , s - i - j)
list(gen_combo_target(3))
output:
[(0, 0, 3),
(0, 1, 2),
(0, 2, 1),
(0, 3, 0),
(1, 0, 2),
(1, 1, 1),
(1, 2, 0),
(2, 0, 1),
(2, 1, 0),
(3, 0, 0)]
Upvotes: 1
Reputation: 675
Take a look at the stars and bars problem. The thing is, even the fastest possible solution will still be very slow because of the sheer number of answers (which can be on the order of N!), and any correct solution needs to get all of them.
Here's my shot at a solution:
def get_combinations(n, k): # gets all lists of size k summing to n
ans = []
def solve(rem, depth, k, cur):
if depth == k:
ans.append(cur)
elif depth == k-1:
solve(0, depth+1, k, cur + [rem])
else:
for i in range(rem+1):
solve(rem-i, depth+1, k, cur+[i])
solve(n, 0, k, [])
return ans
print (get_combinations(3,3))
It's about as fast as it can get as far as finding all the possible lists. However, if you wanted to just find the number of such lists, you could do it much faster using the stars and bars method referenced above.
Upvotes: 0