1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

モンティ・ホール問題が納得いかなかったので、モンテカルロシミュレーションしてみた(2)

Posted at

続き

モンティ・ホール問題が納得いかなかったので、モンテカルロシミュレーションしてみた

シミュレーションの結果、参加者はドアを変更すると賞品を得られる確率が2倍になるのは明らか。
しかし、やはり納得がいかない。
直感的にわからない。
じゃあ、montyさんが賞品のあるドアの位置を知らなかったらどうなる?

早速、コードを修正してみました。

変更箇所

使用前

        if monty_select != select and doors[monty_select] == 0:#賞品が無く、参加者が選ばなかったドアを選ぶ
            break   

使用後

もしmontyが賞品のあるドアを開けてしまったら、その回はなかったことに。
raiseで例外を投げます。
(あまり綺麗なコードではないですが。)

        if monty_select != select:#参加者が選ばなかったドアを選ぶ
            if doors[monty_select] != 0:#もしmontyが選んだドアに賞品があったら。その回はなかったことにする。
                raise
            break      

for i in range(n):#指定回数を繰り返す
    try:
        change += monty(change = True)
    except:
        change_invalid += 1 #montyが賞品のあるドアを開けてしまった。
    try:
        nochange += monty(change = False)
    except:
        nochange_invalid += 1 #montyが賞品のあるドアを開けてしまった。

修正済みコード


import random
import sys

#引数
n = int(sys.argv[1])

#賞を得るのに、成功すると1、失敗すると0を返す
#change ドアを変更するか
#True:変更する
#False:変更しない
def monty(change):
    #3枚のドア
    doors = [0,0,0]
    #乱数でどのドアに賞品があるかを決める
    prize = random.randint(0,2)
    doors[prize] = 1
    #参加者がドアを選ぶ
    select = random.randint(0,2)

    #続いてmontyがドアを選ぶ
    while True:
        monty_select = random.randint(0,2)
        if monty_select != select:#参加者が選ばなかったドアを選ぶ
            if doors[monty_select] != 0:#もしmontyが選んだドアに賞品があったら。その回はなかったことにする。
                raise
            break            

    if change:#ドアを変更する場合
        while True:
            select_change = random.randint(0,2)
            if monty_select != select_change and select != select_change:#montyも参加者も選ばないドア
                select = select_change
                break
    if doors[select] == 1:#賞を得られたら1を返す
        return 1
    return 0#賞が得られなければ0を返す

change = 0
change_invalid = 0
nochange = 0
nochange_invalid= 0
for i in range(n):#指定回数を繰り返す
    try:
        change += monty(change = True)
    except:
        change_invalid += 1 #montyが賞品のあるドアを開けてしまった。
    try:
        nochange += monty(change = False)
    except:
        nochange_invalid += 1 #montyが賞品のあるドアを開けてしまった。

#結果の表示
print("turn",n)
print("change  ",change,"invalid",change_invalid)
print("nochange", nochange, "invalid" ,nochange_invalid)

実行結果

今度は、ドアを変えても変えなくてもほぼ同じになりました。
invalidがmontyが賞品のあるドアを開けてしまって無効となった回数です。
このinvalidの数分に何か原因があるんでしょうけど。
やっぱり直感的には良くわからないですね。。。

turn 1000
change   341 invalid 344
nochange 344 invalid 323

turn 1000
change   325 invalid 346
nochange 382 invalid 313

turn 1000
change   334 invalid 352
nochange 344 invalid 331
1
1
2

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?