简体   繁体   中英

How do you get all the combinations of n numbers divisible by 10 and whose sum is 100?

The objective is to obtain distribution lists that allow, for example, to test scenarios by weighting variables with different familiar weights whose sum is equal to 100 (and therefore assimilable to percentages).

The method I propose below works but may not be the best. Feel free to suggest any improvement.

Function for integer compositions into n parts:

def comppercents(n):
    y = [0] * n
    y[0]  = 100
    while True:
        yield(y)
        v = y[-1]
        if (100 ==v ):
            break
        y[-1] = 0
        j = -2
        while (0==y[j]):
            j -= 1
        y[j] -= 10
        y[j+1] = 10 + v

for x in comppercents(3):
    print(x)


[100, 0, 0]
[90, 10, 0]
[90, 0, 10]
[80, 20, 0]
...
[0, 20, 80]
[0, 10, 90]
[0, 0, 100]

(66 variants)

from itertools import groupby

def comb_100(n):
    global L_combination_100 
    L_combination_100= []

    # adds in L_combination_100 all the possible lists (without the order mattering) whose sum of the elements is 10
    find_raw_combination([i+1 for i in list(range(10))]*10,10)

    # we remove all duplicate lists
    for i in range(len(L_combination_100)):
        L_combination_100[i].sort()
    L_combination_100.sort()
    L_combination_100 = list(k for k,_ in groupby(L_combination_100)) # groupby from itertools

    # We remove all lists that have too many elements (> n)
    L_combination_100 = [i if len(i)<=n else [] for i in L_combination_100]
    L_combination_100 = [x for x in L_combination_100 if x != []]

    # We add 0's to lists that don't have n items
    # All items within each list are multiplied by 10 to obtain a sum equal to 100
    for i,l in enumerate(L_combination_100) :
        if len(l) != n:
            L_combination_100[i].extend([0]*(n-len(l)))
        L_combination_100[i] = [ii*10 for ii in L_combination_100[i]]

    #That's how we got our final list of lists/combinations. We have to be careful that the order doesn't matter in these lists.
    return L_combination_100

#Strongly inspired from https://stackoverflow.com/questions/4632322/finding-all-possible-combinations-of-numbers-to-reach-a-given-sum
def find_raw_combination(numbers, target, partial=[]): # need global variable L_combination_100
    s = sum(partial)

    # check if the partial sum is equals to target
    if s == target: 
        L_combination_100.append(partial) if partial not in L_combination_100 else L_combination_100
    if s >= target:
        return # reach if we get the number

    for i in range(len(numbers)):
        n = numbers[i]
        remaining = numbers[i+1:]
        find_raw_combination(remaining, target, partial + [n])

Example:

comb_100(3)

Output:

[[10, 10, 80],
 [10, 20, 70],
 [10, 30, 60],
 [10, 40, 50],
 [10, 90, 0],
 [20, 20, 60],
 [20, 30, 50],
 [20, 40, 40],
 [20, 80, 0],
 [30, 30, 40],
 [30, 70, 0],
 [40, 60, 0],
 [50, 50, 0],
 [100, 0, 0]]

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