根据提供值的总和和列表分配值

Distribute values based on sum and list of provided values

我需要根据满足此要求的条件生成值列表:

所有生成值的总和应等于total,只应使用providedValues来获得总和,providedValuestotal可以是任何double。

例如:

total = 1.0
providedValues = [0.5, 0.25]

输出列表中的值应随机分布,例如输出可以是:[0.5, 0.25, 0.25][0.25, 0.5, 0.25][0.25, 0.25, 0.5]

如果总和不能等于总数:

total = 1.0
providedValues = [0.3]

算法应该抛出错误。

实施语言无关紧要,我会尝试阅读任何语言。

该算法将 return 所有可能的组合,总和为 total

import itertools
import numpy as np

def find_combination(total, providedValues):
    i = 1
    rv = []
    while True:
        combs = list(itertools.combinations_with_replacement(providedValues,i))
        validCombs = [comb for comb in combs if np.isclose(sum(comb),total)]
        if validCombs:
            rv.extend(validCombs)
        elif not [comb for comb in combs if sum(comb) <= total]:
            return rv
        i += 1

输出:

>>> find_combination(1.0, [0.5, 0.25])
[(0.5, 0.5), (0.5, 0.25, 0.25), (0.25, 0.25, 0.25, 0.25)]
>>> find_combination(1.0, [0.3])
[]

如果想得到结果的所有排列,可以使用

>>> set(itertools.permutations((0.5, 0.25, 0.25)))
{(0.25, 0.25, 0.5), (0.25, 0.5, 0.25), (0.5, 0.25, 0.25)}

例如:

>>> set(y for x in find_combination(1.0, [0.5, 0.25]) for y in itertools.permutations(x))
{(0.25, 0.25, 0.25, 0.25),
 (0.25, 0.25, 0.5),
 (0.25, 0.5, 0.25),
 (0.5, 0.25, 0.25),
 (0.5, 0.5)}

这是我的解决方案,基于提供的两个值,您可能需要根据需要进行更改

from itertools import permutations, combinations

def get_scala(x,y,t):
    # get list of scala combinations
    # find a,b that a*x+b*y = total
    scala_list = []
    amax = int(t // x)  # possible max scala for x
    bmax = int(t // y)  # possible max scala for y
    for i in range(1, amax+1):
        for j in range(1, bmax+1):
            if i*x + j*y == t:  # find the scala combination that == total
                scala_list.append((i, j))
    if scala_list:
        return scala_list
    else:
        print("Warning: cannot add up to the total")

def dist(x, y, scala):
    a, b = scala
    # get a base list with a number of x and b number of y [x,x,y,y,y]
    bl = [x]*a + [y]*b
    # get permutations and using set to get rid of duplicate items
    return set(permutations(bl)) 


for l in get_scala(0.3, 0.2, 1):
    for d in dist(0.3, 0.2, l):
        print(d)

输出看起来像:

(0.2, 0.3, 0.2, 0.3)
(0.2, 0.2, 0.3, 0.3)
(0.3, 0.2, 0.2, 0.3)
(0.3, 0.2, 0.3, 0.2)
(0.3, 0.3, 0.2, 0.2)
(0.2, 0.3, 0.3, 0.2)