爱吱声

标题: 三个红包的问题,让“蟒蛇”来帮你解决 [打印本页]

作者: Highway    时间: 2014-2-24 10:29
标题: 三个红包的问题,让“蟒蛇”来帮你解决
本帖最后由 Highway 于 2014-2-24 13:11 编辑

三个红包的问题,我大概是二十年前在《读者》上看到过。当时杂志的某个角落里就藏着答案:“第二次你应该更新你的选择!”。

当时和宿舍里的朋友们讨论过这个问题,大家认为《读者》给的答案也许有问题,都觉得当裁判/主持人/面试官 拿走一个选择以后,情况起了变化,成了“二选一”的问题,你不改初衷或是改变主意应该无所谓,都是50%的中彩几率。

这个问题现在又给翻腾出来了,大家七嘴八舌的,我也没仔细看。直到 @夏翁 老剑客给出了一段程序以后,我才觉得是不是也该用程序验证一下这个问题了。因计算机可以很方便的进行随机模拟。

严格的说,现在计算机产生的“随机数”不是100%真正的随机数,但是对绝大多数的情况已经是足够好了,所以我们就不再这个细节上纠缠了。以前我在西西河做信息版版主的时候,没事儿也爱弄几句程序说明个问题啥的,那时候多数是用Java或C#,今天换个花样,用一把“蟒蛇(Python)”,也算是与时俱进吧!



程序的语法大家不必细究,看看这个流程就行了(我没有仔细看题,我认为操作过程大概是这样的)。

1. 准备三个红包,随便挑一个作为放钱的真红包
2. 你先来选一个
3. 裁判拿走一个(分两种情况,1:他知道红包的情况,特意拿走一个空的。2,他也不知情,随便从你挑剩的两个红包中拿走一个)
4. 你再次选择(也分两种情况,1:坚持不变,2:换一下选择)
5. 对答案,揭底!

我编了一个小程序,测试了四种可能的情况(Step 3和4的四种组合),其结果显示:

1. 如果裁判知情,拿走一个空包,那你更换选择永远是对的,中彩几率基本上可以增加一倍
2. 裁判如果不知情,随便拿走一个包,那你换不换选择都一样,都只有1/3的中彩概率。


这个结果你能接受吗?

程序贴在下面,大家自己可以改动这玩。如果觉得我的流程有问题,欢迎指出!
  1. # -*- coding: utf-8 -*-
  2. import random

  3. def tryYourLuck(changeMind=False, judgeKnowAnswer=True, printDetail=False):
  4.    removedOne = None
  5.    yourFirstPick = None
  6.    yourFinalPick = None
  7.    realBonusBag = None

  8.    # 1. 准备三个红包
  9.    bonusBags = ['Bag_A', 'Bag_B','Bag_C']
  10.    realBonusBag = random.sample(bonusBags, 1)[0]
  11.    
  12.    # 2. 作出第一次选择
  13.    yourFirstPick = random.sample(bonusBags, 1)[0]

  14.    # 3. 裁判拿走一个红包
  15.    if judgeKnowAnswer: # 他知情,故意拿走一个空的
  16.       for aBag in bonusBags:
  17.          if aBag != realBonusBag and aBag != yourFirstPick:
  18.             removedOne = aBag
  19.             break
  20.    else: #他不知情,瞎拿
  21.       for aBag in bonusBags:
  22.          if aBag != yourFirstPick:
  23.             removedOne = aBag
  24.             break

  25.    # 4. 作出最后选择
  26.    if changeMind: # 改变主意
  27.       yourFinalPick = [bag for bag in bonusBags if bag!= yourFirstPick and bag!=removedOne][0]
  28.    else: # 不变
  29.       yourFinalPick = yourFirstPick

  30.    # 5. 揭谜底
  31.    if printDetail:
  32.       print 'Bouns bag: %s, First pick: %s, removed one: %s, Final pick: %s, you win: %s' % \
  33.           (realBonusBag, yourFirstPick, removedOne, yourFinalPick, \
  34.            str(yourFinalPick == realBonusBag))

  35.    return 1 if yourFinalPick == realBonusBag else 0

  36. def main():
  37.    #1. 先热身两下,看看程序运行怎么回事儿
  38.    print 'Do some demo first'
  39.    for count in xrange(10):
  40.       tryYourLuck(changeMind=False, judgeKnowAnswer=True, printDetail=True)

  41.    print '\nChange Parameter and try again.'
  42.    for count in xrange(10):
  43.       tryYourLuck(changeMind=True, judgeKnowAnswer=False, printDetail=True)

  44.    # 2. 开始计数统计
  45.    testCount = 1000000
  46.    winCount = 0
  47.    loseCount = 0
  48.    for count in xrange(testCount):
  49.       result = tryYourLuck(changeMind=False, judgeKnowAnswer=True, printDetail=False)
  50.       if result ==1:
  51.          winCount +=1
  52.       else:
  53.          loseCount +=1
  54.          
  55.    print '\nCASE 1: If you do not change mind and judge know which one is empty to remove'         
  56.    print 'then you win %d times and you lose %d times' %(winCount, loseCount)
  57.    
  58.    winCount = 0
  59.    loseCount = 0
  60.    
  61.    for count in xrange(testCount):
  62.       result = tryYourLuck(changeMind=True, judgeKnowAnswer=True, printDetail=False)
  63.       if result ==1:
  64.          winCount +=1
  65.       else:
  66.          loseCount +=1
  67.    print '\nCASE 2: If you change mind and judge know which one is empty to remove'
  68.    print 'then you win %d times and you lose %d times' %(winCount, loseCount)

  69.    winCount = 0
  70.    loseCount = 0
  71.    for count in xrange(testCount):
  72.       result = tryYourLuck(changeMind=False, judgeKnowAnswer=False, printDetail=False)
  73.       if result ==1:
  74.          winCount +=1
  75.       else:
  76.          loseCount +=1

  77.    print '\nCASE 3: If you do not change mind and judge does not know which one is empty to remove'
  78.    print 'then you win %d times and you lose %d times' %(winCount, loseCount)

  79.    winCount = 0
  80.    loseCount = 0
  81.    for count in xrange(testCount):
  82.       result = tryYourLuck(changeMind=True, judgeKnowAnswer=False, printDetail=False)
  83.       if result ==1:
  84.          winCount +=1
  85.       else:
  86.          loseCount +=1

  87.    print '\nCASE 4: If you change mind and judge does not knows which one is empty to remove'
  88.    print 'then you win %d times and you lose %d times' %(winCount, loseCount)

  89. if __name__ == "__main__":
  90.    main()
复制代码

作者: Highway    时间: 2014-2-24 10:30
本帖最后由 Highway 于 2014-2-24 11:00 编辑

运行的时候,先弄弄参数,把过程打出来,你可以检查一下程序是不是按你设计的来运行。然后再开始做大量的模拟和统计。

运行的结果是
  1. >>>
  2. Do some demo first
  3. Bouns bag: Bag_A, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_A, you win: True
  4. Bouns bag: Bag_C, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_C, you win: True
  5. Bouns bag: Bag_A, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_A, you win: True
  6. Bouns bag: Bag_B, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_C, you win: False
  7. Bouns bag: Bag_C, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_A, you win: False
  8. Bouns bag: Bag_A, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_A, you win: True
  9. Bouns bag: Bag_B, First pick: Bag_A, removed one: Bag_C, Final pick: Bag_A, you win: False
  10. Bouns bag: Bag_B, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_B, you win: True
  11. Bouns bag: Bag_B, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_B, you win: True
  12. Bouns bag: Bag_C, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_B, you win: False

  13. Change Parameter and try again.
  14. Bouns bag: Bag_C, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_C, you win: True
  15. Bouns bag: Bag_B, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_C, you win: False
  16. Bouns bag: Bag_C, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_C, you win: True
  17. Bouns bag: Bag_B, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: True
  18. Bouns bag: Bag_A, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: False
  19. Bouns bag: Bag_A, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: False
  20. Bouns bag: Bag_C, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: False
  21. Bouns bag: Bag_B, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_C, you win: False
  22. Bouns bag: Bag_B, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: True
  23. Bouns bag: Bag_A, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: False

  24. CASE 1: If you do not change mind and judge know which one is empty to remove
  25. then you win 33208 times and you lose 66792 times

  26. CASE 2: If you change mind and judge know which one is empty to remove
  27. then you win 666444 times and you lose 333556 times

  28. CASE 3: If you do not change mind and judge does not know which one is empty to remove
  29. then you win 333512 times and you lose 666488 times

  30. CASE 4: If you change mind and judge does not knows which one is empty to remove
  31. then you win 333080 times and you lose 666920 times
复制代码

作者: 懒厨    时间: 2014-2-24 10:37
Highway 发表于 2014-2-24 10:30
运行的时候,先弄弄参数,把过程打出来,你可以检查一下程序是不是按你设计的来运行。然后再开始做大量的模 ...

没细看代码,光看答案,case 2 和 case 4 好像重复。

照道理,如果评判随机拿走红包的话,似乎概率应该是一致的。。。。。
作者: Highway    时间: 2014-2-24 10:45
懒厨 发表于 2014-2-24 10:37
没细看代码,光看答案,case 2 和 case 4 好像重复。

照道理,如果评判随机拿走红包的话,似乎概率应该 ...

谢谢提醒,最后一个Case是和第二个重复了,程序改过来了,结论也变了
作者: 巴巴爸爸    时间: 2014-2-24 11:11
能不能直接发红包。。。。。
作者: 独角兽    时间: 2014-2-24 11:37
哈哈,编程狂人轧叔也来了
作者: 常挨揍    时间: 2014-2-24 11:42
原题裁判/主持人/面试官拿走一个空包是假设条件,现在大家把它当成默认条件,解题思路错了

假设条件下,是三选一的题目再加提示
默认条件下,是二选一的题目
作者: 常挨揍    时间: 2014-2-24 12:47
本帖最后由 常挨揍 于 2014-2-24 12:52 编辑

再啰嗦一句
“我”选择一个红包,分为A组,中奖概率是1/3,
剩下的两个红包,分为B组,中奖概率是2/3,

无论红包是否打开,无论裁判把红包“拿”到哪儿去,AB两组的中奖概率是不会变的

凯文史派西《21点》里面也用了这个段子
作者: 石头布    时间: 2014-2-24 18:10
赞!跟夏教授一样都是认真的人。




欢迎光临 爱吱声 (http://aswetalk.net/bbs/) Powered by Discuz! X3.2