ビンゴの確率の問題をJavaScriptで解いてみた。

 ビンゴの確率の問題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]