简体   繁体   中英

Finding(or Generating) all possible combinations(at a given length) of positive numbers that equals a given sum.(python)

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?

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)]

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.

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)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM