使用值数组最佳地对值进行切片

时间:2014-11-14 00:20:52

标签: javascript arrays math division greatest-common-divisor

问题

想象一下以下场景:

有一个代表瓦数的数值:

var w = 1000; // 1000 watts

然后有一个包含各种变压器的阵列,涵盖了某些瓦数:

var transformers = [240, 200, 100, 50, 20];

目标是创建一个数组,其中包含transformers所需的任意数量的值,以涵盖按w定义的瓦数需求。

但是,生成的数组必须包含尽可能少的元素,因此大数字首先出现。但是,也必须有最小的损失,因此,除了分裂留下的任何内容,应尽可能用最小的数量(来自transformers)。

目标只是计算所需的变压器,以最小的损耗(尽可能使用较小的变压器,但使用最少量的变压器)。

示例1

w = 1000;
transformers = [260, 200, 100, 50];
results = [260, 260, 260, 260];

示例2

w = 1042;
transformers = [260, 200, 100, 50];
results = [260, 260, 260, 260, 50];

实施例3

w = 502;
transformers = [220, 180, 60, 30];
results = [220, 220, 180];

我的方法

当然我自己试图解决这个问题,但是由于我的大脑缺乏数学计算能力,我失败了。

我的方法是:

  1. 创建一个包含可用瓦数的数组,按降序排列
  2. 循环超过总瓦数要求(w的副本),直到总瓦数为0或更低
  3. 将总瓦数要求除以可用的最大变压器
    1. 如果除法结果大于,则将电流互感器推到结果数组并从总瓦数中减去当前瓦数
    2. 如果除法结果小于,则移动变换器阵列以移除阵列中最大的变压器
  4. 如果变换器阵列只剩下一个元素,请将其推送到结果数组并将总瓦数设置为0
  5. 结果接近正确,但在某些情况下结果证明是错误的,因为可以做出更多的最佳选择来覆盖瓦数。我还有一些案例,当时没有发现瓦数。

    我的代码

    // test values:
    var wattages = [264, 100, 60, 35, 18];
    var _wattageTotal = 1000; // 1000 watts
    
    var _trafos=new Array(); // for the results
    
    console.log('-----------------------');
    console.log('THESE ARE THE AVAILABLE WATTAGES:');
    console.log(wattages);
    
    while(_wattageTotal){
    
        console.log('WATTAGE TOTAL: '+_wattageTotal);
        console.log('TESTING: '+wattages[0]+' against total wattage => '+_wattageTotal/wattages[0]);
    
        if( _wattageTotal/wattages[0] >= 1 ) {
    
            console.log('==> FOUND FIT: '+wattages[0]);
            _trafos.push( byWattage[ wattages[0] ].key );
            _wattageTotal-=wattages[0];
    
        } else {
    
            console.log(wattages[0]+' DOES NOT FIT');
            wattages.shift();
    
            if(wattages.length==1){
                _trafos.push( byWattage[ wattages[0] ].key );
                _wattageTotal=0;
            }
    
        }
    
    }
    

2 个答案:

答案 0 :(得分:0)

请勿将_wattageTotal设置为0。当你这样做时退出while循环,当前_trafos未涵盖的任何剩余将被忽略

您还需要在执行length =1检查后调整当前瓦数,并检查_wattageTotal>在你的while循环中为0:

var wattages = [264, 100, 60, 35, 18];
var _wattageTotal = 82; // 1000 watts

var _trafos=new Array(); // for the results

console.log('-----------------------');
console.log('THESE ARE THE AVAILABLE WATTAGES:');
console.log(wattages);

while(_wattageTotal > 0){

    console.log('WATTAGE TOTAL: '+_wattageTotal);
    console.log('TESTING: '+wattages[0]+' against total wattage => '+_wattageTotal/wattages[0]);

    if( _wattageTotal/wattages[0] >= 1 ) {

        console.log('==> FOUND FIT: '+wattages[0]);
        _trafos.push( wattages[0] );
        _wattageTotal-=wattages[0];

    } else {

        console.log(wattages[0]+' DOES NOT FIT');

        if(wattages.length==1){
            _trafos.push(  wattages[0]  );
            _wattageTotal -= wattages[0];
        }

        wattages.shift();
    }

}

jsfiddle

答案 1 :(得分:0)

经过更深入的研究,测试,一些失败的方法和一些咖啡,这是最终的结果。

// test values

var wattage=600;
var trafos=[264, 100, 60, 35, 18];

var g, i, results=[];

// since wattage can also end up below zero,
// we loop until it is no longer greater than zero

while(wattage>0){

    // each run, we want an empty array g

    g=[];

    // we iterate over all available trafos

    for (i in trafos){

        // g will contain our division factors, but since
        // we want to be able to sort this array, we must
        // use an object literal

        g.push({

            // g.k = the factor of the division (total wattage / trafo wattage)

            k: wattage/trafos[i],

            // g.v = the trafo wattage, as reference, so we know which 
            // division factor belongs to which trafo

            v: trafos[i]

        });

    }

    // now, g will contain the division factors for all trafo wattages
    // against the current wattage that needs to be covered
    // naturally these will range from 0 to X
    // we then use a sort function to sort this array
    // by which values are closest to 1 (= which trafos fit best for the current
    // wattage) but with the values SMALLER than 1 having more priority than
    // the ones being greater

    g.sort(function(a, b){
        var dis=Math.abs(1-a.k) - Math.abs(1-b.k);
        if(a.k<1 && b.k>=1){ return -1; }
        if(a.k>=1 && b<1){ return 1; }
        return dis;
    });

    // naturally, the first element of g will now contain the trafo
    // which covers best for the wattage that needs to be covered for,
    // so we push its wattage (using g.v) into the results array

    results.push( g[0].v );

    // finally we can now subtract the wattage from the total wattage
    // that still needs to be covered for

    wattage -= g[0].v;

}

高级解释

而不是使用缩小的数组。我们采用不同的方法:对于我们检查和匹配的每个值,我们创建一个包含相应除法因子的数组。

然后我们使用一个非常神奇的排序函数对该数组进行排序,该函数执行两项操作:

  • 它根据值与1
  • 的接近程度对值进行排序
  • 优先选择小于1的值,而不是大于
  • 的值

(此信用转到user BatScream谁提供此功能以回答我的问题Sorting an array by which value is closest to 1

我最初使用sort函数提出了这个解决方案,但只对最接近1的值进行排序。这样做有效,但仍导致非最佳计算,例如:

wattage = 600;
trafos=[264, 100, 60, 35, 18];

result = [264, 264, 60, 18];

最好的结果是:

result = [264, 264, 100];

因此,我们的目标是相应地调整排序功能,这样它仍然可以选择最大的可用于静止覆盖功能的trafo。

现在我的大脑被炸了,我终于可以安息了。