今日は、モンティ・ホール問題をプログラムを使って体感してみようと思います。
モンティ・ホール問題の詳細はウキペディアを参照していただくこととして、簡単に説明すると
「3つの箱の中に当たりが一つあります。今、挑戦者に当たりの入ってそうな箱を一つ選んでもらいました。司会者は当たりがどこにあるかを知っています。さらに司会者は挑戦者が選ばなかった2つの箱から一つを選んで開け、そこに当たりが入っていないことを挑戦者に確認させます。そして最後に司会者は、挑戦者が選んだほうかこの開けなかった箱のどちらかに確実に当たりが入っているが、今なら挑戦者は選択を変えることができると言います。さて、挑戦者は、初めに選んだものを最後まで通せばいいか、あるいはここで選択を変えたほうがいいか?」
ちょと話が新婚さんいらっしゃいのたわしかヨーロッパかにも似てますね![]()
さて、あなたならどうします? 臨機応変に箱を変えてみる?それとも外れたときに悔しいから初志貫徹?
お気づきの方も多いかと思いますが、これちゃんと答えがあるんです。好みの問題じゃないんです。そう、正解は「箱を選びなおす」です。ここで納得の方は、以下不要です。
ええ??どちらも当たる確率50%じゃないのと思っている方残念です。選びなおしたら当たる確率は66.66%に跳ね上がり、そのままだと33.33%しか当たりません。
なぜか
初めに選んだほうは、たとえ司会者が外れをオミットしたところで当たる確率は変わりません。
もう少しわかりやすく考えるため逆を考えてみましょう。
もし、あなたが3つの箱のうち2つを選べたとしたら当たる確率は3分の2になるというのは納得できますね。そのうち無条件で外れが消えてなくなったとします。するとどうでしょう。あなたは箱1つしかないのにあたる確率は3分の2のままだということです。
この直感で50%が実は違ったという論争はウキペディアによると数学者も巻き込んだらしいです。
では、UWSCを使って検証してみましょう。UWSCはumiumiさん開発のスクリプト言語です。キジも大好きで、たいていのものはこれで何とかなります。
//------------------------------------------------------
// モンティ・ホール問題 実験
// Monty_Hall_problem.uws
実験回数 = input("実験回数(数値)を入力してください")
if ! chknum(実験回数) then exit
dim 当初当選回数 = 0
dim 再選当選回数 = 0
for n=1 to 実験回数
//箱リセット
dim hako[2] = "はずれ", "はずれ", "はずれ"
//当たり番号決定 atari_no は当たりの箱番号
// 1000までの乱数を発生させ、それを3で割った余りが当たり番号とする
tmp = random(1000)
atari_no = tmp mod 3
//箱にあたりをセットする
hako[atari_no] = "あたり"
//初めに箱を選ぶ picup_no は選んだ箱の番号 (当たりの確立1 / 3)
tmp = random(1000)
//箱番号決定
picup_no = tmp mod 3
//もし司会者のおすすめを再選択したときはどうなるか?
//残りの箱からひとつの外れ箱をオミットし、残りを再選択する作業
//2つの残りの箱に当たりがある確率は 2 / 3
//残りの箱は ①はずれ、はずれ or ②あたり、はずれ、③はずれ、あたり
//②③の場合は、自動的に当たりを引ける
select picup_no
case 0
if hako[1] = "はずれ" then re_pic = 2 else re_pic = 1 //残りのhako[1] hako[2]
case 1
if hako[2] = "はずれ" then re_pic = 0 else re_pic = 2 //残りのhako[0] hako[2]
case 2
if hako[0] = "はずれ" then re_pic = 1 else re_pic = 0 //残りのhako[0] hako[1]
selend
//結果 初めに選んだのが当たる場合 or 選びなおしたほうが当たる場合
if hako[picup_no] = "あたり" then 当初当選回数 = 当初当選回数 + 1
if hako[re_pic] = "あたり" then 再選当選回数 = 再選当選回数 + 1
next
当初率 = 当初当選回数 / 実験回数 * 100
再選率 = 再選当選回数 / 実験回数 * 100
print "実験回数" + 実験回数 + "回" + "<#CR>"
print "初めに選んだのが当たった回数は" + 当初当選回数 + "回"
print "初めに選んだのが当たる確率は" + 当初率 + "%" + "<#CR>"
print "選びなおして当たった回数は" + 再選当選回数 + "回"
print "選びなおして当たる確率は" + 再選率 + "%"
//-----------------------------------------------------------------
実験回数を増やすほど、選びなおしたほうの当たる確率が3分の2に近づきますね。