鍍金池/ 問答/HTML/ 茶后一道算術(shù)題

茶后一道算術(shù)題

本人最近經(jīng)常腦抽,容易產(chǎn)生幻想! 求治療!

這道題并非來自于 產(chǎn)品需求, 而是在sf看帖子的時(shí)候意淫的時(shí)候產(chǎn)生的!

需求:

寫一算法 ,滿足以下三個(gè)條件即可!
條件一:5個(gè)數(shù) 和值為100;
條件二:5個(gè)數(shù) 的每個(gè)數(shù)值 波動(dòng)范圍 為 16 - 24;
條件三:每種組合出現(xiàn)的概率必須為 1/3951 ,也就是 萬分之3.5 ( 下面做說明 );

條件三說明 : 窮舉出 所有 組合

var sum = 0 , q ,w ,r ,t,y ;
for (q = 16; q < 25 ; q ++ ) {
    for (w = 16; w < 25 ; w ++ ) {
        for (r = 16; r < 25 ; r ++ ) {
            for (t = 16; t < 25 ; t ++ ) {
                for (y = 16; y < 25 ; y ++ ) {
                    if((q + w + r + t + y) == 100){
                        sum ++;
                    }
                }
            }
        }
    }
}
console.log(sum);  // 總共有 3951 組合情況, 那么每一種出現(xiàn)的概率應(yīng)該是 1/3951;

我自己寫了個(gè) 函數(shù),下面直接貼代碼:(代碼很原始,請(qǐng)輕噴?。?/p>

function ran() {
    var a, b, c, d, e, average, sum = 0, str2 = "", arr = [];
    a = parseInt(Math.random() * 9) + 16;
    b = parseInt(Math.random() * 9) + 16;

    average = (100 - (a + b ))/ 3;
    if ((average - 16) > (24 - average )) {
        c = parseInt(Math.random() * parseInt(24 - average) *2 ) + parseInt(average - parseInt(24 - average));
    }else {
        c = parseInt(Math.random() * parseInt(average - 16) *2 ) + parseInt(average - parseInt(average - 16));
    }

    average = (100 - (a + b + c))/ 2;
    if ((average - 16) > (24 - average )) {
        d = parseInt(Math.random() * parseInt(24 - average) *2 ) + parseInt(average - parseInt(24 - average));
    }else {
        d = parseInt(Math.random() * parseInt(average - 16) *2 ) + parseInt(average - parseInt(average - 16));
    }
    e = 100 - a - b - c - d;
}

基本思路: 先隨機(jī)兩個(gè),然后再根據(jù)前面生成的兩個(gè)數(shù),改變后面的數(shù)的 波動(dòng)區(qū)間。
然而檢查中發(fā)現(xiàn):?jiǎn)栴}那么多!?。?/p>

1、用5000000次循環(huán)檢查 所以可能出現(xiàn)的 組合數(shù) 為2248, 也就是說少了接近2000中可能;
2、循環(huán)1000000次,檢查其中 兩三種 出現(xiàn)的概率 
    (20 ,20 ,20,20 ,20)出現(xiàn)的概率波動(dòng)比較大在170-210之間,
    (20 ,19 ,21,20 ,20)出現(xiàn)的概率 在230-270之間 ,這個(gè)還概率還是比較合理,
    (24 ,19 ,21,20 ,16)出現(xiàn)的概率 為 0,這個(gè).....
    

各位路過的大神,就當(dāng) 茶后 笑談,給鄙人點(diǎn)亮 知識(shí)之光,賜予我 高明的 思路吧,阿門!

回答
編輯回答
孤酒

先把幾千種可能性放到數(shù)組里
再shift 得出概率可控
時(shí)間復(fù)雜度o(0)

__

多次隨機(jī)必會(huì)壓縮解空間
t1大神專門說過

2018年8月18日 00:42
編輯回答
柒喵

感覺概率要均衡的話,不能是每個(gè)數(shù)一次。數(shù)的概率均衡了。最后的結(jié)果的概率就不均衡。數(shù)的概率應(yīng)該要不均衡。比如符合條件結(jié)果里第一個(gè)數(shù)20出現(xiàn)了10次,17出現(xiàn)了5次(ps:亂猜的。表示想法)
代碼大概的結(jié)構(gòu)應(yīng)該是這樣


var ran_num = function(sum, count) {
    var next_num = Math.random();
    switch(count) {
        case 1:
            return sum;
        case 2:
            return 16 + parseInt((sum - 16 * 2) * next_num);
        case 3: 
            // TODO
        case 4: 
            // TODO
        case 5: 
            // TODO
    }
    return next_num;
};
var run = function() {
    var created_nums = [], sum = 0, num;
    for (var i = 0; i < 5; i++) {
        num = ran_num(100 - sum, 5 - i);
        sum += num;
        created_nums.push(num);
    }
    return created_nums.join('-');
};
2017年3月16日 14:24
編輯回答
舊言

檢查的方法是
檢查1 :所有組合的總數(shù)目

  var str2 = "", arr = []; 

  str2 = "" + a + b + c + d + e;
  if (arr.indexOf(str) == -1) {
       arr.push(str2);
  }
  console.log(arr.length); // 循環(huán) 5000000次 打印值為2248

檢查2 : 其中一種出現(xiàn)的概率數(shù)

if (a == 20 && b == 19 && c ==21 && d ==20 && e ==20){
   sum ++;
}
console.log(sum) // 循環(huán)1000000次 打印值在 170 -210 之間波動(dòng)
2018年6月18日 12:18
編輯回答
傻叼

貌似你說的是「波動(dòng)均分算法」。你說的條件三我當(dāng)時(shí)也有考慮實(shí)現(xiàn),不過沒有想到好的思路可以實(shí)現(xiàn)這一點(diǎn),希望有大神可以提供個(gè)思路

2017年5月19日 08:59
編輯回答
忠妾
var arr = []
var q ,w ,r ,t ,y
for (q = 16; q < 25 ; q ++ ) {
    for (w = 16; w < 25 ; w ++ ) {
        for (r = 16; r < 25 ; r ++ ) {
            for (t = 16; t < 25 ; t ++ ) {
                for (y = 16; y < 25 ; y ++ ) {
                    if((q + w + r + t + y) == 100){
                        arr.push([q, w, r, t, y])
                    }
                }
            }
        }
    }
}
const index = Math.floor(Math.random() * 3951)
return arr[index]

(逃

2017年8月18日 23:27