ビンゴの確率の問題をJavaScriptで解いてみました。
教室には 1人の先生と32人の生徒がいます。
生徒たちは、3×3の9マスに 1〜9の数字をランダムに書きます。
その後、先生は1〜9の3つの数字を言います。
その数字で、32人の生徒の誰かが縦横斜どこか ビンゴになる確率は?
昨日の組合せ生成プログラムは、これの伏線でした。(^_^;
一人の生徒が全くビンゴしない確率pを全パターンについて実際にカウントして求めて、32人のうち少なくとも一人はビンゴする確率1-p^32を求めています。
ちなみに、C++なら、実行時間は、7[秒]ぐらいです。
●Bingo.html
<html> <head> <title>Bingo.html</title> <script type="text/javascript"> function next_perm(p, n, r) // 順列生成 { var i, j, k, tmp; if(r <= 0 || n < r) return(false); for(i = r + 1; i <= n-1; i++) for(j = i; j >= r + 1 && p[j-1] < p[j]; j--) tmp = p[j], p[j] = p[j-1], p[j-1] = tmp; for(i = n - 1; i > 0 && p[i-1] >= p[i]; i--); if(i == 0) return(false); for(j = n - 1; j > i && p[i-1] >= p[j]; j--); tmp = p[i-1], p[i-1] = p[j], p[j] = tmp; for(k = 0; k <= ((n-1)-i)/2; k++) tmp = p[i+k], p[i+k] = p[(n-1)-k], p[(n-1)-k] = tmp; return(true); } // xがaの何番目にあるか調べる関数 function get_pos(a, x) { var i; for(var i=0; i< a.length; i++) if(a[i]==x) return(i); // あるときは、0〜a.length-1を返す return(-1); // ないときは、-1を返す } // 組合せ生成 function next_comb(c, n, r) { var i,j,k; if(r <= 0 || n < r) return(false); var o=new Array(n+1); var p=new Array(n+1); o=c.slice(0).sort(); for(i=0; i< n; i++) p[i]='1'; for(i=0; i< r; i++) p[get_pos(o,c[i])]='0'; var res=next_perm(p, n, n); if(!res) n=0; for(i=j=0,k=r; i< n; i++) if(p[i]=='0') c[j++]=o[i]; else c[k++]=o[i]; delete o,p; return(res); } function isBingo(p,q,r,s) // p,q,rは生徒用、sは配列で先生用 { var t; // 三値のソート if(p>q) {t=p;p=q;q=t;} if(q>r) {t=q;q=r;r=t;} if(p>q) {t=p;p=q;q=t;} if(p==s[0] && q==s[1] && r==s[2]) return(true); else return(false); } </script> </head> <body> <script type="text/javascript"> var cnt=0,total=0; var o=[1,2,3,4,5,6,7,8,9]; o=o.sort(); // 念のためのソート var p=o.slice(0); var q=o.slice(0); var tm=(new Date()).getTime(); // Timer start do{ // 先生が書いた3つの数字の組合せのループ p=o.slice(0); // pの初期化 do{ // 生徒が書いた数字の順列のループ total++; // すべての場合をカウント if(isBingo(p[0],p[1],p[2],q)) continue; if(isBingo(p[3],p[4],p[5],q)) continue; if(isBingo(p[6],p[7],p[8],q)) continue; if(isBingo(p[0],p[3],p[6],q)) continue; if(isBingo(p[1],p[4],p[7],q)) continue; if(isBingo(p[2],p[5],p[8],q)) continue; if(isBingo(p[0],p[4],p[8],q)) continue; if(isBingo(p[2],p[4],p[6],q)) continue; // チェックを潜り抜けたものだけをカウント cnt++; // ビンゴしなかったものをカウント }while(next_perm(p,9,9) ); }while(next_comb(q,9,3)); document.write("p=",cnt," / ",total,"<br>"); var prb=cnt/total; document.write("=",prb,"<br>"); document.write("∴1-p^32=",1-Math.pow(prb,32),"<br>"); tm=(new Date()).getTime()-tm; // Timer stop document.write("Runtime : ",tm/1000.0, "[sec]<br>"); </script> </body> </html>
●実行結果
p=27578880 / 30481920 =0.9047619047619048 ∴1-p^32=0.9593465133339257 Runtime : 12.623[sec]