Python證明“三門選擇”問題

一、啥是三門問題?

電影《決勝21點》裏面提到的一個經典問題。假如現在有一個這樣遊戲,在你面前有三個門,其中只有一個門有一份禮物,其他兩個門是空的,現在主持人讓你選擇一個門,然後他會從剩下的兩個門中,打開一個空門,再來問你,你是否要改變你原來選擇的那個門,還是堅持選擇,如果你選的門後面有禮物,打開後禮物就是你的。

如上圖,三扇門是ABC,現在A門是有禮物,BC門是空,如果你一開始選了A門,主持人會打開B、C門中的任意一扇,然後問你,你是否改變你的選擇;如果你一開始是選擇了B或C,主持人會打開剩下的一扇空門,然後指着A門問你,你是否改變你原來的選擇?

二、怎麼選擇?

說實話,咱資質愚鈍,一開始看到這個問題一臉懵逼,但本着固執、怕被主持人欺騙的態度,選擇了不改變自己原來的選擇,你問我爲什麼,我只能回答, 要你管,我樂意!

但是如果咱們把上面的問題稍微改一下,所有人立馬能會選擇改變自己的第一選擇。我們把三扇門改成100扇門,在你選擇一扇門後,主持人把剩下的98扇空門全部打開,然後再問你,你改不改變自己原來的選擇時,你難道還不會改變自己的第一選擇?

這其實很簡單,就是一個概率的問題。三扇門,只有一扇有禮物,當你選擇一扇門時,你就把三門分成2部分樣本(咱們假設這兩個樣本爲甲和乙,甲樣本代表的是你選擇的那扇門,中獎的概率是1/3,乙樣本是剩下兩扇門,中獎的概率是2/3),假設在不作弊的前提下,主持人把乙樣本中的一扇空門排除了,但乙樣本的中獎概率沒有改變,還是2/3,此時如果改變自己的第一選擇,你的中獎概率就變成了2/3,爲啥不改呢。

三、腳本跑一下就知道

注:一下代碼參考了微信作者“作者吹牛Z”的文章https://mp.weixin.qq.com/s/dwH52G95CEh7E6VRSm1NNg

先定義一個函數,能每次產生N次1-3的list

#定義函數,隨機生成Num次
def gen_random(num):
    #獎品在A,B,C門中隨機出現
    lst = np.random.randint(1,4,size = num)
    return lst

 這裏有兩種選擇,第一種選擇就是一開始選擇哪扇門就一直堅持哪扇門;第二種選擇就是改變最初的選擇,這個有兩種可能,第一種可能就是你開始選對了,但是改變選擇後就選錯了,一種是你一開始選錯了,改變選擇後就選對了,下面的腳本就是按照這種思路寫的(其實還有另一種更簡單的思路,就是判斷你第一次選擇是否是對的,如果是對的,那麼你這一次的選擇就錯了,如果第一次選擇錯了,那麼你這次選擇就判定爲對了)

#  猜法一,堅持最初的選擇
#定義基於第一種猜法的函數
def guess_one(num):
    #生成正確的答案
    lst = gen_random(num)
    #猜的輪數和前面生成的輪數一致,這裏默認玩100次(生成100次正確答案,對應猜100次)
    guess = np.random.randint(1,4,size = len(lst))
    #計算有多少個正確的,相等即爲正確,最終返回FALSE和TRUE的序列
    judge = (lst == guess)
    #因爲TRUE默認是1,FALSE默認是0,我們直接求和,來計算正確率是多少
    correct_rate = judge.sum() / len(judge)
    print('我們玩%d次' % num)
    print('在第二次不改變選擇的策略下,你最終的中獎率是:%.2f' % (correct_rate * 100))

#猜法二,改變最初的選擇
def guess_two(num):
    #和上面一樣,隨機生成100次正確答案
    lst = gen_random(num)
    #第一步,依然是隨機猜100次
    guess = np.random.randint(1,4,size = len(lst))
    #因爲第二次我們會改變選擇,這裏創建一個列表來存儲我們改變後的最終選擇
    guess_change = []

    for anwser,g in zip(lst,guess):

        #無論是否中獎,在主持人第一次打開門階段,我們選擇的門不會被打開,背後是大獎的門也不會被打開(有時候可能是同一個)
        #舉個栗子:當我們選擇的是A門,大獎藏在B門,那主持人幫我們打開的空門一定是C門,然後問我們是否改變選擇
        #也就是說,當我們第一步猜的和正確答案不一致,改變選擇之後一定會中獎

        #anwser是正確答案,g是我們第一步猜的
        if anwser != g:
            #如果正確答案和我們第一次猜的不一致,主持人排除掉一個門之後我們那改變選擇,肯定選的是正確答案——i
            guess_change.append(anwser)

        else:
            #當我們猜的門和正確答案一致,主持人隨機打開一扇門之後,我們會選擇剩下的一扇未被打開的空門
            #繼續舉栗子:如果我們猜的A門,大獎就在A門,那麼真理既然被我們選中,主持人在沒有獎的B和C門中隨機打開一扇都可以
            #然後問我們是否change,要是B門被打開,那麼剩下A(我們第一步選擇的)和C門,我們改變立場會轉向C門,結果就是大獎飛走了

            anwser_range = [1,2,3]
            #我們選擇的就是正確答案,先排除掉(因爲最後我們會改變選擇)
            anwser_range.remove(anwser)
            #主持人隨機打開一個門
            anwser_range.remove(anwser_range[np.random.randint(0,1)])

            #剩下的一個就是我們最終選擇的門
            guess_change.append(anwser_range[0])

    #到這一步,我們對剛纔改變選擇之後的結果進行彙總
    guess_change = np.array(guess_change)
    #看看猜對了多少輪
    judge = (lst == guess_change)
    #正確率是多少
    correct_rate = judge.sum() / len(judge)
    print('我們玩%d次' % num)
    print('在第二次改變選擇的策略下,你最終的中獎率是:%.2f' % (correct_rate * 100))

跑了100次,結果如下。(跟拋硬幣的道理一樣,如果你把次數改到100000次甚至更多,概率更加接近於1/3) 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章