Highway 发表于 2014-2-24 10:29:03

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

本帖最后由 Highway 于 2014-2-24 13:11 编辑

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

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

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

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

http://www.python.org/static/community_logos/python-logo-master-v3-TM-flattened.png

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

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

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

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

这个结果你能接受吗?

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

def tryYourLuck(changeMind=False, judgeKnowAnswer=True, printDetail=False):
   removedOne = None
   yourFirstPick = None
   yourFinalPick = None
   realBonusBag = None

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

   # 3. 裁判拿走一个红包
   if judgeKnowAnswer: # 他知情,故意拿走一个空的
      for aBag in bonusBags:
         if aBag != realBonusBag and aBag != yourFirstPick:
            removedOne = aBag
            break
   else: #他不知情,瞎拿
      for aBag in bonusBags:
         if aBag != yourFirstPick:
            removedOne = aBag
            break

   # 4. 作出最后选择
   if changeMind: # 改变主意
      yourFinalPick =
   else: # 不变
      yourFinalPick = yourFirstPick

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

   return 1 if yourFinalPick == realBonusBag else 0

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

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

   # 2. 开始计数统计
   testCount = 1000000
   winCount = 0
   loseCount = 0
   for count in xrange(testCount):
      result = tryYourLuck(changeMind=False, judgeKnowAnswer=True, printDetail=False)
      if result ==1:
         winCount +=1
      else:
         loseCount +=1
         
   print '\nCASE 1: If you do not change mind and judge know which one is empty to remove'         
   print 'then you win %d times and you lose %d times' %(winCount, loseCount)
   
   winCount = 0
   loseCount = 0
   
   for count in xrange(testCount):
      result = tryYourLuck(changeMind=True, judgeKnowAnswer=True, printDetail=False)
      if result ==1:
         winCount +=1
      else:
         loseCount +=1
   print '\nCASE 2: If you change mind and judge know which one is empty to remove'
   print 'then you win %d times and you lose %d times' %(winCount, loseCount)

   winCount = 0
   loseCount = 0
   for count in xrange(testCount):
      result = tryYourLuck(changeMind=False, judgeKnowAnswer=False, printDetail=False)
      if result ==1:
         winCount +=1
      else:
         loseCount +=1

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

   winCount = 0
   loseCount = 0
   for count in xrange(testCount):
      result = tryYourLuck(changeMind=True, judgeKnowAnswer=False, printDetail=False)
      if result ==1:
         winCount +=1
      else:
         loseCount +=1

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

if __name__ == "__main__":
   main()

Highway 发表于 2014-2-24 10:30:57

本帖最后由 Highway 于 2014-2-24 11:00 编辑

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

运行的结果是>>>
Do some demo first
Bouns bag: Bag_A, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_A, you win: True
Bouns bag: Bag_C, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_C, you win: True
Bouns bag: Bag_A, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_A, you win: True
Bouns bag: Bag_B, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_C, you win: False
Bouns bag: Bag_C, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_A, you win: False
Bouns bag: Bag_A, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_A, you win: True
Bouns bag: Bag_B, First pick: Bag_A, removed one: Bag_C, Final pick: Bag_A, you win: False
Bouns bag: Bag_B, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_B, you win: True
Bouns bag: Bag_B, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_B, you win: True
Bouns bag: Bag_C, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_B, you win: False

Change Parameter and try again.
Bouns bag: Bag_C, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_C, you win: True
Bouns bag: Bag_B, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_C, you win: False
Bouns bag: Bag_C, First pick: Bag_A, removed one: Bag_B, Final pick: Bag_C, you win: True
Bouns bag: Bag_B, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: True
Bouns bag: Bag_A, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: False
Bouns bag: Bag_A, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: False
Bouns bag: Bag_C, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: False
Bouns bag: Bag_B, First pick: Bag_B, removed one: Bag_A, Final pick: Bag_C, you win: False
Bouns bag: Bag_B, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: True
Bouns bag: Bag_A, First pick: Bag_C, removed one: Bag_A, Final pick: Bag_B, you win: False

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

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

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

CASE 4: If you change mind and judge does not knows which one is empty to remove
then you win 333080 times and you lose 666920 times

懒厨 发表于 2014-2-24 10:37:53

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

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

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

Highway 发表于 2014-2-24 10:45:09

懒厨 发表于 2014-2-24 10:37 static/image/common/back.gif
没细看代码,光看答案,case 2 和 case 4 好像重复。

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

谢谢提醒,最后一个Case是和第二个重复了,程序改过来了,结论也变了{:229:}

巴巴爸爸 发表于 2014-2-24 11:11:21

{:200:}{:201:}{:218:}{:224:} 能不能直接发红包。。。。。

独角兽 发表于 2014-2-24 11:37:48

哈哈,编程狂人轧叔也来了{:232:}

常挨揍 发表于 2014-2-24 11:42:09

原题裁判/主持人/面试官拿走一个空包是假设条件,现在大家把它当成默认条件,解题思路错了

假设条件下,是三选一的题目再加提示
默认条件下,是二选一的题目

常挨揍 发表于 2014-2-24 12:47:40

本帖最后由 常挨揍 于 2014-2-24 12:52 编辑

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

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

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

石头布 发表于 2014-2-24 18:10:01

赞!跟夏教授一样都是认真的人。{:222:}
页: [1]
查看完整版本: 三个红包的问题,让“蟒蛇”来帮你解决