モンティホール問題をプログラムで再現したけど全くスッキリしなかった話

シェアする:

この記事をおすすめしたい人

  • モンティホール問題は間違ってると思う人
  • モンティホール問題をプログラムで解決したい人
  • つまりオレ

前回知ったAlpine.jsの練習がてら、何か面白い題材ないかなーと探してました。

そうだ、モンティホール問題だ!

というわけで、モンティホール問題をAlpine.jsで再現して、1000回とかガンガン試行させて、

ほんまに選択肢を変えた方がええんかいな?

という疑問を圧倒的物量でねじ伏せます。

モンティホール問題って?

僕が知ったのはこのチャンネルの動画だったかな。

テキストの解説より動画の方が絶対に分かりやすいので、モンティホール問題を知らない人は上の動画を見てください。

簡単に説明すると、

ここに3つの箱があります。

1個だけ当たりが入っています。

あなたは箱をひとつ選びます。

残った2つからハズレの1個を僕が除外します。

最初の箱のままと、残った箱を選ぶのと、

どっちが当たりやすいと思いますか!

という問題です。

感覚的には「どっちも同じでしょ」って思いがちなんだけど、実際は残った箱を選ぶ方が2倍当たりやすいそうです。

なんでや!?

一応、理屈としては、最初の箱が当たる確率は1/3で、残った方を選ぶのは実質「残り2個まとめて選ぶ」ことになるから2/3になる、みたいな説明があるんだけど、

そんなもん知るか!!

他にも「箱を100個に増やす」バージョンがあって、その場合、最初の箱が当たる確率は1/100まで下がります。 そこからハズレ98個を除外して、残った1個と最初の箱を比べると、感覚的にも「そりゃ残った箱を選ぶ方が有利だよね」って分かりやすくなる、みたいな説明もあって、

98個も除外したら当たり前やろ!!

となってですね、なんかズルいと思うんですよね。 3個の時の「1個除外」という条件が、単純に「1個除外」だったのか、「1個を残して除外」だったのかは分からないわけじゃないですか。

3個の時こそ絶妙なバランスで、そこに「1個を残して除外」ルールをそのまま当てはめた説明って、ほんとに「分かりやすい説明」になってるのか?

だからプログラムで物量検証だ!

モンティホール問題をプログラムで再現

ではプログラムにしていきましょう。

まずは当たり番号をランダムに決めます。


const atari = Math.floor(Math.random() * 3);

「Math.random()」は1未満の少数がランダムに返るので、3をかけると0~2.999…の範囲になります。 これを切り捨てすると0か1か2となり、ちょうど箱を配列にした時の番号になります。

次に最初に選んだ箱を考えます。 ここもランダムに選んでもいいんだけど、実は1個目の箱に固定しても結果は変わらないので、0番に固定しちゃいます。

肝心の「箱を変えるかどうか」は、要するに当たり番号が0かどうか。 0番が当たりなら「変えずに当たったケース」、0番以外なら「変えたら当たったケース」になるわけです。


const atari = Math.floor(Math.random() * 3);

if ( atari == 0 ) {
  //箱を変えずに当たった
} else {
  //箱を変えたら当たった
}

……ん?

あとは1000回ループで回して、当たり数をひたすら集計するだけ。


let kaenai = 0;
let kaeru = 0;

for ( let i = 0; i < 1000; i++ ) {
  const atari = Math.floor(Math.random() * 3);
  
  if ( atari == 0 ) {
    kaenai++;
  } else {
    kaeru++;
  }
}

いや、これって…。

プログラムに1000回計算させた結果

上のルーチンを基本に、ちょこちょこUIを整えて、いざ1000回のシミュレーションです。

さてさて、どうなることやら。

(画像なのでクリックできません)

だいたい2倍だ!ざまぁみろ!

いやいやいや、違うやん!?

さっきのコードならそらそうなるやん!?


const atari = Math.floor(Math.random() * 3);

if ( atari == 0 ) {
  //箱を変えずに当たった
} else {
  //箱を変えたら当たった
}

0~2の値を取る「atari」に対して、0かどうかで分けてるだけだから、0の時が1/3、0以外の時が2/3になるのは当然。 0をランダムな番号にしても同じことです。

つまりこのコードは「モンティホール問題を解いた」というより、最初から2/3になるように条件を決め打ちしてただけなんです。

あのコードで本当にモンティホール問題を再現できてるのか怪しいし、そもそもあのモヤモヤ感をコードで表現できるのかどうかも分からないし、

プログラムでスッキリ解決することはできません!

……と、強引にまとめておきます。

あ。

作ったツールは公開してあるので、

遊んでみてね。

シェアする: