モンティ・ホール問題
モンティ・ホール問題というのがある。
「プレイヤーの前に3つのドアがあって、1つのドアの後ろには景品の新車が、2つのドアの後ろにはヤギ(はずれを意味する)がいる。プレイヤーは新車のドアを当てると新車がもらえる。プレイヤーが1つのドアを選択した後、モンティが残りのドアの内ヤギがいるドアを開けてヤギを見せる。
ここでプレイヤーは最初に選んだドアを、残っている開けられていないドアに変更しても良いと言われる。プレイヤーはドアを変更すべきだろうか?」
Wikipediaの説明を読んでも、どうもよく分からない。プログラムを書いてシミュレーションしてみるとどうなるのだろうか。最近知ったarc4random()を使って、計算してみる。
#import <Foundation/Foundation.h> const int N = 3; // プレイヤーはモンティがヤギのドアを開いても選択を変えない void montyHall(int n) { // n:試行回数 int hit = 0; for (int i = 0; i < n; i++) { int car = arc4random() % N; // 商品の位置 int p = arc4random() % N; // プレイヤーが選んだ位置 if (car == p) hit++; } NSLog(@"ドアを変更しない"); NSLog(@"%d/%d %f%%", hit, n, 1.0*hit/n*100); } // プレイヤーはモンティがヤギのドアを開いた後、選択を変える void montyHall2(int n) { // n:試行回数 int hit = 0; for (int i = 0; i < n; i++) { int car = arc4random() % N; // 商品の位置 int p = arc4random() % N; // プレイヤーが選んだ位置 // モンティがヤギのドアを開ける // プレイヤーは選択したドアを変更する if (car != p) hit++; } NSLog(@"ドアを変更する"); NSLog(@"%d/%d %f%%", hit, n, 1.0*hit/n*100); } int main(int argc, const char * argv[]) { @autoreleasepool { const int n = 10000000; montyHall(n); montyHall2(n); } return 0; }
実行結果です。
ドアを変更しない 3333261/10000000 33.332610% ドアを変更する 6666672/10000000 66.666720%
このプログラムで正しいのかはよく分からない。
そういえばと思って、『数学ガール』でこの問題を扱っていたのを思い出した。『数学ガール 乱択アルゴリズム』の1章で出てくる。そこでは全ての可能性を表にまとめて、確率を計算している。なるほど、表で考えるとわかりやすい。