やんちょふのブログ

ご連絡はTwitterアカウント@syoyuu616にて受け付けております

【Python3】モンティホール問題

ふとモンティホール問題について気になったので、スクリプトを書いて実験してみました。

#coding: utf-8
import random

def set_door():
    rand_num = random.randint(0, 2)
    if rand_num == 0:
        door = (1, 0, 0)
    elif rand_num == 1:
        door = (0, 1, 0)
    else:
        door = (0, 0, 1)
    return door

def pre_open_door(door, selected):
    for i in range(0, 3):
        if i != selected and door[i] == 0:
            return i

def re_select_door(door, opened, selected):
    for i in range(0, 3):
        if i != selected and i != opened:
            return i

if __name__ == "__main__":
    count = 0
    select_right_count = 0
    reselect_right_count = 0

    for i in range(1000000):
        door = set_door()
        select = random.randint(0, 2)
        opened = pre_open_door(door, select)
        re_select = re_select_door(door, opened, select)
        if door[re_select] == 1:
            reselect_right_count += 1
        if door[select] == 1:
            select_right_count += 1
        count += 1

    print("reselect:", reselect_right_count/count)
    print("non reselect:", select_right_count/count)

実験結果

  • 1回目
    reselect: 0.666524
    non reselect: 0.333476

  • 2回目
    reselect: 0.666154
    non reselect: 0.333846

  • 3回目
    reselect: 0.665123
    non reselect: 0.334877

再選択する場合の確率は0.6666...で再選択しない場合の確率は0.3333...なので 実験結果から正しい確率(に近い値)が得られています。

プログラミング初心者なのであまりきれいなコードではありませんが、とりあえず モンティホール問題の正解確率が出せたので今回はこれで良しとします。すっきりした。

追記
もっと簡単にできました。というより元のコードが長すぎました。

#coding: utf-8
import random
N = int(input("N: "))           #扉の数
cycle = int(input("cycle: "))   #試行回数
blank_door = tuple([0] * (N-1) + [1])
count = 0
reselect_right_count = 0
select_right_count = 0
for i in range(100000):
    door = list(blank_door)
    random.shuffle(door)
    selected = door.pop(random.randint(0, len(door)-1))
    for i in range(len(door)-1):
        door.remove(0)
    if (door[0] == 1):
        reselect_right_count += 1
    if (selected == 1):
        select_right_count += 1
    count += 1
print("reselect: ", reselect_right_count/count)
print("non_reselect :", select_right_count/count)

これでもまだきれいじゃありませんね。聞くところによると1行で書けるらしいですが 初心者の私にはわかりません