2017-01-19 9 views
1

セットの長さの数値の配列を作成し、そのセットの最小値と最大値を定義し、その間の残りの数字。キッカーは、この数列の合計が所定の値と等しくなければならないということです。そのトリックは、その機能がどのように機能するかを調べることです。値の配列を返す方法(合計値は指定した数値に等しい)

私は私に、以下の機能を持っている、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; 
} 

最初の部分の試行をし、値を配信するが、常に私は大きい値で終わりますまたは入力量よりも少ないので、それを修正する方程式の2番目の部分があります。しかし、少し汚れているようですが、残りの部分がどのように分布するかは少し恣意的なので、純粋な数学的な解決策は素晴らしいでしょう。

私は基本的に積分(配列の値の合計)、積分の範囲(最小値と最大値)、そして現在ではこれを計算に必要としているのだろうかと思い始めています曲線の公式を把握しなければならない。しかし、これは現時点では過度なことかもしれません。

ありがとうございました!

+0

あなたが知る必要があることは、JavaScriptが数値をどのように格納しているかで、計算が混乱する可能性があることです(例:0.1 + 0.2!== 0.3)。たとえば、[このページでは、この問題についていくつか説明しています](https://modernweb.com/what-every-javascript-developer-should-know-about-floating-points/)を参照してください。 –

+0

よろしくお願いします。ありがとうございます! – stubbly

+0

サンプル入力と期待される出力を含めると、大いに役立ちます。あなたは、最小値と最大値、その数と合計を指定したいとしますが、それらのためのパラメータではないようです。 – RobG

答えて

0

これはいかがですか?まず、最初のメンバーが最小であり、2番目のメンバーが最小+ 1、3番目の最小+ 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; 
} 
+0

ここでセットが作成されました最小値と最大値を含むことはできません。セットに最小値と最大値が含まれている必要がある場合は、最初にsetLengthを2だけ短くし、minを1増やし、maxを1減らしてpreDetからminとmaxを減算してから、同じプロセスを実行します。最後に、minとmaxを結果セットに追加するだけです。 – Shiping

関連する問題