设为首页收藏本站

爱吱声

 找回密码
 注册
搜索
查看: 2347|回复: 8
打印 上一主题 下一主题

[其他] 三个红包的问题,让“蟒蛇”来帮你解决

[复制链接]
  • TA的每日心情
    开心
    2015-12-23 04:08
  • 签到天数: 2 天

    [LV.1]炼气

    跳转到指定楼层
    楼主
    发表于 2014-2-24 10:29:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本帖最后由 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()
    复制代码

    评分

    参与人数 7爱元 +36 收起 理由
    韦红雪 + 8 不明觉厉!
    不感冒 + 8 谢谢!有你,爱坛更精彩
    逆天废柴 + 2 高大上!不明觉厉!
    sduivy + 4 涨姿势
    MacArthur + 8 谢谢!有你,爱坛更精彩

    查看全部评分

  • TA的每日心情
    开心
    2015-12-23 04:08
  • 签到天数: 2 天

    [LV.1]炼气

    沙发
     楼主| 发表于 2014-2-24 10:30:57 | 只看该作者
    本帖最后由 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
    复制代码

    评分

    参与人数 1爱元 +2 收起 理由
    人在江湖 + 2 不明觉厉

    查看全部评分

  • TA的每日心情
    郁闷
    2017-8-30 00:17
  • 签到天数: 321 天

    [LV.8]合体

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

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

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

    评分

    参与人数 1爱元 +6 收起 理由
    Highway + 6 谢谢指出我的Bug!

    查看全部评分

  • TA的每日心情
    开心
    2015-12-23 04:08
  • 签到天数: 2 天

    [LV.1]炼气

    地板
     楼主| 发表于 2014-2-24 10:45:09 | 只看该作者
    懒厨 发表于 2014-2-24 10:37
    没细看代码,光看答案,case 2 和 case 4 好像重复。

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

    谢谢提醒,最后一个Case是和第二个重复了,程序改过来了,结论也变了
  • TA的每日心情
    开心
    2016-4-24 12:49
  • 签到天数: 7 天

    [LV.3]辟谷

    5#
    发表于 2014-2-24 11:11:21 | 只看该作者
    能不能直接发红包。。。。。

    点评

    油墨: 5.0 油菜: 5.0
    给力: 5.0
    油墨: 5 油菜: 5 给力: 5
    +10086  发表于 2014-2-24 13:01
    我看行,轧叔是个慷慨的大财主呦。。。  发表于 2014-2-24 11:38

    该用户从未签到

    6#
    发表于 2014-2-24 11:37:48 | 只看该作者
    哈哈,编程狂人轧叔也来了
  • TA的每日心情
    慵懒
    前天 17:11
  • 签到天数: 1926 天

    [LV.Master]无

    7#
    发表于 2014-2-24 11:42:09 | 只看该作者
    原题裁判/主持人/面试官拿走一个空包是假设条件,现在大家把它当成默认条件,解题思路错了

    假设条件下,是三选一的题目再加提示
    默认条件下,是二选一的题目
  • TA的每日心情
    慵懒
    前天 17:11
  • 签到天数: 1926 天

    [LV.Master]无

    8#
    发表于 2014-2-24 12:47:40 | 只看该作者
    本帖最后由 常挨揍 于 2014-2-24 12:52 编辑

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

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

    凯文史派西《21点》里面也用了这个段子

    该用户从未签到

    9#
    发表于 2014-2-24 18:10:01 | 只看该作者
    赞!跟夏教授一样都是认真的人。

    手机版|小黑屋|Archiver|网站错误报告|爱吱声   

    GMT+8, 2024-4-29 06:50 , Processed in 0.045979 second(s), 24 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表