怎么得到能被10整除且和为100的n个数的所有组合?

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

objective 是为了获得分布列表,例如,通过对具有不同熟悉权重的变量进行加权,其总和等于 100(因此可以同化为百分比)来测试场景。

我在下面提出的方法可行,但可能不是最好的。欢迎提出任何改进建议。

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

示例:

comb_100(3)

输出:

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

将整数组合成 n 部分的函数:

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 种变体)