Monty Hall問題 #1

問題に沿って素直に書いてみる。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int i, iter, n_car[2], n_goat[2];
    for (i = 0; i < 2; i++) n_car[i] = n_goat[i] = 0;
    srand48(20111222L);
    for (iter = 0; iter < 1000000; iter++) {
        int car = (int)(drand48() * 3);
        int select = (int)(drand48() * 3);
        int open, switches, choice;
        if (select == car) {
            open = ((int)(drand48() * 2) + select + 1) % 3;
        } else {
            open = ((select + 1) % 3 == car ? select + 2 : select + 1) % 3;
        }
        switches = (int)(drand48() * 2);
        if (switches) {
            choice = ((select + 1) % 3 == open ? select + 2 : select + 1) % 3;
        } else {
            choice = select;
        }
        if (choice == car) {
            n_car[switches]++;
        } else {
            n_goat[switches]++;
        }
    }
    for (i = 0; i < 2; i++) printf("%d %d %d\n", n_car[i], n_goat[i], n_car[i] + n_goat[i]);
    printf("%d %d %d\n", n_car[0] + n_car[1], n_goat[0] + n_goat[1], n_car[0] + n_goat[0] + n_car[1] + n_goat[1]);
    return 0;
}

ドアに0, 1, 2の番号を振る。
carは当たりのドア番号、selectは最初に解答者が選んだドア番号、
carとselectから決定されるopenは出題者が開いた外れのドア番号、
switchesは0か1を取り、最初の選択を変える(1)か変えない(0)かの解答者による選択、
choiceは最終的に解答者が選んだドア番号、を表している。
とりあえず100万回ほどこれを繰り返したときに、
n_car[0]とn_goat[0]が解答者が最初の選択を変えなかった時の当たりと外れの回数、
n_car[1]とn_goat[1]が解答者が最初の選択を変えた時の当たりと外れの回数、これらをカウントする。
乱数の種も適当に。
結果は、

166817 332732 499549
333403 167048 500451
500220 499780 1000000

最初の選択を変えなかった場合に当たった割合は0.334、変えた場合に当たった割合は0.666になる。