愛と自由と段ボール箱

cryptoboxの微妙にうまくいかない日々

プログラミング初心者がPythonでモンティ・ホール問題を検証してみた

こんにちは!cryptobox(くりぷとぼっくす)です。

今回はある有名な心理トリックであるモンティ・ホール問題をプログラミングで検証してみました。

f:id:cryptobox:20180331181656p:plain

モンティ・ホール問題とは

モンティ・ホール問題を知らない人は特に気を張らず、以下の問題を考えてみてください。

f:id:cryptobox:20180331184228p:plain

今あなたの目の前にA,B,C,3つのドアがあります。3つのドアのうち2つはハズレで、ドアを開けるとヤギがいます。のこりの1つがアタリです。開けると1億円が置いてあり、そのドアを選ぶことができれば持ち帰ることができます。

f:id:cryptobox:20180331184749p:plain

今、あなたはCのドアを選びました。するとAのドアが開いて中からヤギが出てきました。
さて、あなたはCのドアを選んでいますが、今なら選択するドアをBに変えることができます。あなたはドアを変えますか?それとも変えませんか?

 

 

 

 

 

初めて友人にこの問題を出されたとき僕はハッキリNOと言いました。

「いや、Bを選ぼうがCのままだろうがアタリを引く確率はどちらも1/2だろ」

 

ところが、選ぶドアは変えた方が良いのです。何故ならドアを変えるとアタリを引く確率は2倍になるからです。

 

これは納得できない方も多いと思います。僕自身全く信じられず友人に向かって「そんなわけない」とわめきたてましたから笑

 

その後以下のサイトを見せてもらい一応腑に落ちたのですが、やっぱり自分で検証してみたいと思い、絶賛勉強中のPythonでプログラムを書いてみました。

 
↓モンティ・ホール問題の解説
全米を騒然とさせた確率の問題・モンティ・ホール問題とは


 

Pythonで検証してみた

def MontyHall_problem(): # 関数の定義
num = input("試行回数を入力してください:") # 試行回数の入力
num = int(num) # 入力された文字列を数値化
Door = ["False", "False", "True"] # ドアの設置
Rules = {(0, "False"):0, (1, "False"):1, (2, "False"):2,
(0, "True"):3, (1, "True"):4, (2, "True"):5} # 選ぶドアのパターン
Change = 0 # 変数の初期化
Stay = 0 # 変数の初期化

for i in range(num): # ドアを変える場合
random.shuffle(Door) # ドアをシャッフル
First_Choice = randint(0, 2) # 初めに選ぶドア
Select = Door[First_Choice] # 初めに選んだドアのアタリorハズレ

if Rules[(First_Choice, Select)] < 3: # アタリを選んだ場合
Change = Change + 1 # インクリメントを行う

for j in range(num): # ドアを変えない場合
random.shuffle(Door) # ドアをシャッフル
First_Choice = randint(0, 2) # 初めに選ぶドア
Select = Door[First_Choice] # 初めに選んだドアのアタリorハズレ

if Select == "True": # アタリを選んだ場合
Stay = Stay + 1 # インクリメントを行う

print("ドアを変えた場合:%d回【%d%%】\nドアを変えなかった場合:%d回【%d%%】 " % (Change,Change*100/num,Stay,Stay*100/num)) # 結果の表示


100行くらいのコード書かなきゃいけないかなーって思ってたんですけど、なんか20行程度に納まりました笑。


f:id:cryptobox:20180409212513p:plain


作成した関数を実行すると試行回数を求められます。ひとまず300と入力します。
すると以下のような結果が帰ってきました。


f:id:cryptobox:20180409213134p:plain


これはドアを変えた場合は300回中202回アタリを引き、ドアを変えなかった場合は300回中92回アタリを引いたことを示しています。理論上はドアを変えた場合アタリを引く確率は約66%、変えなかった場合は33%になるはずなのでまだ誤差があります。

そこで大数の法則に基づき試行回数を100倍の30000回にしてみましょう。


f:id:cryptobox:20180409212903p:plain


理論値の66%と33%になりました!
(ドアを変えた場合):(ドアを変えなかった場合)=2:1となり、確かにドアを変えるとアタリを引く確率が2倍になることが確認できました。

まとめ

いかがだったでしょうか?Pythonのプログラムは改良すればもっとシンプルに書けそうですが、今回は力尽きたのでここまでにしておきます。

実際にプログラムを書いてみるとモンティ・ホール問題のパラドクスの正体が見えてきました。

すなわちプレイヤーが最初にアタリのトビラを選択すると、ドアを変えたとき必ずハズレを引き、ハズレを選択するとドアを変えたとき必ずアタリを引くのです。

外れのドアは3個中2個ですから、ドアを変えると2/3の確率でアタリを引くことができるということなんですね。