一、啥是三門問題?
電影《決勝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)