求一个红包算法

m个硬币,n个红包,红包里的硬币数不可以小于b,也不可以大于t,数目是随机的。

mnt均为自然数,且 n*b<=m<=n*t。

求红包算法

function getRedPackets(m,n,b,t){

         var ret = new Array(n);

         /*todo*/

         return ret;

}

示例代码 http://wagang.net/hongbao.html

<!doctype html>
<html>
 <head>
  <meta charset="UTF-8">
  <title>红包算法--JK</title>
 </head>
 <body>

m个硬币,n个红包,红包里的硬币数不可以小于b,也不可以大于t,数目是随机的。<br>
mnt均为自然数,且 n*b<=m<=n*t。
<hr><input id=m value=100 style="width:50px">个硬币,<input id=n value=10 style="width:50px">个包,每人最少<input id=b value=1 style="width:50px">,最多<input id=t value=100 style="width:50px"> <input type=button value="生成红包" onclick="生成红包()"> <input type=button value="分析数据" onclick="分析数据()"> <input type=button value="清空数据" onclick="清空数据()"><hr>
<textarea id=result style="width:800px;height:300px;"></textarea>
<script>

function g(id){
    return document.getElementById(id);
}


function getRedPackets(m,n,b,t){ //
    /* 代码思路:
     * 每次生成一个红包k,k需满足以下条件:
     * b <= k <=t  并且 (n-1)*b <= m-k <= (n-1)*t;
     * 所以,k的取值范围是[Math.max(b, m-(n-1)*t),Math.min(t,m-(n-1)*b)];
    */
    var ret = [];
    while(n>1){
        n--;
        var kMin = Math.max(b, m-n*t),
            kMax = Math.min(t,m-n*b),
            kAvg = m/(n+1),
            kDis = Math.min(kAvg - kMin,kMax - kAvg);
        var k = Math.round(kAvg+ 2*(Math.random()-0.5)*kDis); //本句使用平均分布,待改进。目前写法导致:1红包分布域不够宽,2后取的红包方差大。
        m -= k;
        ret.push(k);
    }
    ret.push(m);
    return ret;
}

//以下为测试代码,请忽不用改
function 生成红包(){
    var m=g('m').value,
        n=g('n').value,
        b=g('b').value,
        t=g('t').value;

    if((m|0)!=m || (n|0)!=n || (b|0)!=b || (t|0)!=t) return alert('请检查您的输入');
    if(n*b>m*1 || n*t<m*1) return alert('不符合“n*b<=m<=n*t”');
    var ret = getRedPackets(m,n,b,t),
        total=0;
    for(var i=0;i<ret.length;i++){
        total += ret[i];
    }    
    g('result').value += getRedPackets(m,n,b,t).join('\t')+'\t'+total+'\n';
}

function 分析数据(){
    var data = g('result').value.replace(/\s+$/g,'').split(/[\r\n]+/);
    for(var i=0;i<data.length;i++) {
        data[i] = data[i].split(/\t/);
        if(data[i].length != data[0].length){
            return alert('数据不统一,无法分析,建议清空数据重新生成再分析');
        }
    }
    if (data.length<2){
        return alert('数据太小,无法分析');
    }
    var avg = [],
        delta = []
        luck = [];

    for(var j=0;j<data[0].length;j++){
        avg[j] = 0;
        delta[j] = 0;
        luck[j] = 0;
    }
    for(var i=0;i<data.length;i++) {
        var tempLuck=0,
            max = data[i][0];
        for(var j = 0;j<data[i].length;j++){
            avg[j] += (data[i][j]|0);
            if(data[i][j]>max){
                max=data[i][j];
                tempLuck = j;
            }
        }
        luck[tempLuck]++;
    }
    for(var j = 0;j<avg.length;j++){
        avg[j] = avg[j]/data.length;
    }

    for(var i=0;i<data.length;i++) {
        for(var j = 0;j<data[i].length;j++){
            delta[j] += Math.pow((data[i][j]-avg[j]),2);
        }
    }
    for(var j = 0;j<avg.length;j++){
        delta[j] = Math.pow(delta[j]/data.length,0.5);
    }

    for(var j = 0;j<avg.length;j++){
        avg[j] = avg[j].toFixed(2);
        delta[j] = delta[j].toFixed(2);
    }

    g('result').value += avg.join('\t')+'\t平均值\n';
    g('result').value += delta.join('\t')+'\t方差值\n';
    g('result').value += luck.join('\t')+'\t最佳手气\n';

}

function 清空数据(){
    g('result').value ='';

}
</script>
 </body>
</html>

 

posted on 2016-05-10 11:19  JKisJK  阅读(739)  评论(0编辑  收藏  举报

导航