如何返回一个值数组,其总和等于指定的数字

时间:2017-01-19 22:33:42

标签: javascript arrays distributed curve

我正在尝试创建一组设定长度的数字,定义集合中的最小数字和最大数字,并让函数确定其间的数字。踢球者是这个数字数组的总和必须等于预定值。诀窍在于弄清楚这个功能是如何运作的。

我找到了this on stack overflow,它给了我以下功能:

export const distributeValues = (amount, weights=[]) => {
    const distributedAmounts = []
    let totalWeights = weights.reduce( (a,b) => a + b)

    weights.forEach( weight => {
        const weightValue = parseFloat(weight)
        const percentage = weightValue / totalWeights
        const distributedAmount = Math.round(percentage * amount)
        distributedAmounts.push(distributedAmount)
        totalWeights -= weightValue
        amount -= distributedAmount
    })

    return distributedAmounts
}

这似乎是一个好的开始,但我实际上需要向后工作;我试图弄清楚一个函数,它会给我传递给上述函数的权重。

现在,我有这个,一个功能分为两部分(道歉为冗余):

export const getDistributions = (amount, distributions, modifier) => {
    const values = []
    let amountLeft = amount;
    for (let i = 0; i < distributions; i++ ) {
        const value = Math.max(Math.round((amountLeft / (modifier || 4))),1)
        amountLeft -= value
        values.push(value)
    }

    // -------------------------------------------- //
    // --- correct for cases where total values --- //
    // --- end up greater/less than amount      --- //
    // -------------------------------------------- //

    let iterator = 0
    let totalAssignedValue = values.reduce((a,b) => a+b);

    const lastIndex = (values.length - 1);
    const getIndex = (iterator, values) => {
        return iterator > lastIndex ? iterator % lastIndex : iterator
    }

    while (totalAssignedValue > amount) {
        iterator = getIndex(iterator)
        if (iterator !== lastIndex && iterator !== 0 && values[iterator] > 1) {
            values[iterator]--
        }
        iterator ++
        totalAssignedValue = values.reduce((a,b) => a+b);
    }
    while (totalAssignedValue < amount) {
        iterator = getIndex(iterator)
        if (iterator !== lastIndex && iterator !== 0) {
            values[iterator]++
        }
        iterator ++
        totalAssignedValue = values.reduce((a,b) => a+b);
    }

    // -------------------------------------------- //
    // -------------- end correction -------------- //
    // -------------------------------------------- //

    return values;
}

第一部分尝试并分配值,但总是最终得到的值大于或小于输入量,因此方程的第二部分修复了这一点。虽然看起来有点不干净,但剩余部分如何分配有点随意,所以纯粹的数学解决方案会很棒。

我开始怀疑我是否需要微积分,因为我基本上有积分(数组值的总和),积分范围(最小值和最大值),现在有找出曲线的公式。不过,现在这可能有点过头了。

感谢您的投入!

1 个答案:

答案 0 :(得分:0)

这个怎么样?首先以第一个成员为最小值,第二个成员为最小值+ 1,第三个最小值为+ 2等方式创建集合。然后对集合中的数字求和并从预定值中减去总和。然后在概述的集合中的所有数字中分配减法的结果。

Set makeSet(int preDet, int min, int max, int setLength)
{
    if((max + max - setLength + 1) * setLength / 2 < preDet) return null;
    if((min + min + setLength - 1) * setLength / 2 > preDet) return null;
    Set set = Set(setLength);
    int val = min;
    for (int i = 0; i < setLength; i++)
    {
        set[i] = val++;
    }
    int sum = (min + val - 1) * setLength / 2;
    int dev = preDet - sum;
    if(dev)
    {
        int adj = dev / setLength;
        if(dev % setLength) adj++;
        for(int i = setLength -1; dev; i--)
        {
            if(adj > dev) adj = dev;
            set[i] += adj;
            dev -= adj;
        }
    }
    return set;
}