LoginSignup
34
27

More than 5 years have passed since last update.

「モンティ・ホール問題」の簡単なシミュレーションプログラムを書いてみる

Posted at

モンティ・ホール問題は「主観的な答えと確率論にのっとった答えが一致しない」という不思議な問題です。今回はこの「モンティ・ホール問題」の簡単なシミュレーションプログラムを書いてみました。経験主義万歳!


import random

def monty_hall():
    # 0,1,2の扉からランダムに正解が選ばれる
    answer = random.randrange(3)

    # 解答者は0,1,2から好きな扉を選ぶ
    first_choice = random.randrange(3)

    # 司会者であるモンティははずれの扉をひとつ開く
    monty_choice = random.choice(tuple({0, 1, 2} - {answer, first_choice}))

    # 解答者は2回目の選択として、最初に選んだ扉とは違う扉を選択する
    second_choice = ({0, 1, 2} - {first_choice, monty_choice}).pop()

    # 2回目に選んだ扉は正解なのか?
    return answer == second_choice

if __name__ == '__main__':
    for x in (10, 100, 1000, 100000):
        # x回の試行中、monty_hall()がTrueを返した回数を記録する。
        win = sum(1 for _ in range(x) if monty_hall())
        print("試行回数{0}回のときの確率 : {1}".format(x, win / x))

# 試行回数10回のときの確率 : 0.7
# 試行回数100回のときの確率 : 0.58
# 試行回数1000回のときの確率 : 0.673
# 試行回数100000回のときの確率 : 0.66657

「モンティ・ホール問題」最大の論点は「司会者がはずれの扉を見せた後、挑戦者は最初の選択を変えるべきか」というところにありますが、「変えたほうが正解である確率が高い」ということが確かめられました。

ちなみに上記のコードはわかりやすいよう、やや冗長な書き方をしていますが、次のようにリファクタリングすることもできます。

def refactoring_month_hall():
    # 0,1,2の扉からランダムに正解が選ばれる
    answer = random.randrange(3)

    # 解答者は0,1,2の扉から好きなものを選ぶ
    first_choice = random.randrange(3)

    # 最初に選んだ扉が正解ではない => もう一つの扉が正解
    return answer != first_choice

if __name__ == '__main__':
    for x in (10, 100, 1000, 10000, 100000):
        win = sum(1 for _ in range(x) if refactoring_month_hall())
        print("試行回数{0}回のときの確率 : {1}".format(x, win / x))

# 試行回数10回のときの確率 : 0.8
# 試行回数100回のときの確率 : 0.65
# 試行回数1000回のときの確率 : 0.678
# 試行回数10000回のときの確率 : 0.6676
# 試行回数100000回のときの確率 : 0.66585

こちらでも「最初の選択ではない扉をえらぶほうがよい」ということがはっきりわかります。不思議ですね(´・ω・`)

34
27
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
27