调试:用Python /随机随机播放卡片组

时间:2013-12-18 05:04:55

标签: python algorithm random shuffle

我知道标题听起来很无聊,因为很多人已经问过这个话题了。我希望它可以帮助我深入了解随机模块的工作原理。问题是,我写了两个不同的函数,我认为应该是相同的,但我得到的结果并不相同,我不明白为什么。

我希望最终得到一张“洗得很好的套牌”。我只关心卡片是红色还是黑色,所以我的套牌非常简单。我称之为“1”红色和“0”黑色。

我的想法是通过附加1(红色)来构建套牌,如果random.random()是> .5,否则为0(黑色),然后当我达到一种颜色的26(甲板的一半)时自动附加1或0。但是出了点问题。 deckmaker()无法正常工作,尽管deckmaker2()可以正常工作。任何人都可以提供见解吗?

import random

def deckmaker():
    deck = []
    for i in range(52):
        if deck.count(0) == 26:
            deck.append(1)
        elif deck.count(1) == 26:
            deck.append(0)
        elif random.random() > .5:
            deck.append(0)
        else:
            deck.append(1)
    return deck

def deckmaker2():
    newdeck = []
    for i in range(26):
        newdeck.append(0)
    for i in range(26):
        newdeck.append(1)
    deck = []
    for i in range(52):
        x = random.randint(0,len(newdeck)-1)
        deck.append(newdeck.pop(x))
    return deck

注意:在写这个问题的时候,我发现了random.shuffle列表操作符,它与我的第二个函数做了同样的事情,所以当然让洗牌后的表变得容易。但我仍然想知道为什么我的原始代码不会做同样的事情。

已编辑:很抱歉对deckmaker()的确切问题一无所知。问题是,我并不完全明白什么是错的。它与它产生的甲板上的事实有关,当你逐一“翻转”卡片时,有一些策略可以让你预测“下一张牌”是红色还是黑色不是使用random.shuffle

创建的套牌

编辑2: [更多信息]我将解释我是如何确定甲板制造商不起作用的,如果这很重要的话。 我正在编写这个程序来模拟这里发布的拼图:http://www.thebigquestions.com/2013/12/17/tuesday-puzzle-4/

我的策略是记住最后几张牌,然后用这些信息决定何时决定拿下一张牌。我想也许在连续获得5张“黑色”牌之后,现在是预测“红色”的好时机。我这样实现了它:

mycards = []

for j in range(1000):
    mydeck = deckmaker(52)
    mem_length = 5
    mem = []
    for c in range(mem_length):
        mem.append(4)
    for i in range(len(mydeck)):
        if mem.count(0) == mem_length:
            mycards.append(mydeck[i])
            break
        elif i == len(mydeck)-1:
            mycards.append(mydeck[i])
            break
        else:
            mem.append(mydeck[i])
            mem.pop(0)


x = float(mycards.count(1))

print x/len(mycards)

结果超过一半的卡片(放入列表中的卡片)都是“红色”,这是我通过连续5张红色卡后取卡而获得的结果。这没有任何意义,所以我寻找一种不同的方式来创建甲板并获得更正常的结果。但我仍然不知道我原来的套牌有什么问题。

2 个答案:

答案 0 :(得分:5)

一般来说,除非你能够严格证明它正常工作,否则你永远不要相信随机化方法是正确的。这通常很难。

为了深入了解您的问题,让我们概括一下有问题的功能:

import random

def deckmaker(n):
    half = n // 2
    deck = []
    for i in range(n):
        if deck.count(0) == half:
            deck.append(1)
        elif deck.count(1) == half:
            deck.append(0)
        elif random.random() > .5:
            deck.append(0)
        else:
            deck.append(1)
    return deck

这是一个小司机:

from collections import Counter
c = Counter()
for i in range(1000):
    c[tuple(deckmaker(2))] += 1
for t in sorted(c):
    print t, c[t]

运行:

(0, 1) 495
(1, 0) 505

所以两种可能性大致相同。好!现在尝试一个4号甲板;只需更改相关行:

c[tuple(deckmaker(4))] += 1

运行:

(0, 0, 1, 1) 236
(0, 1, 0, 1) 127
(0, 1, 1, 0) 133
(1, 0, 0, 1) 135
(1, 0, 1, 0) 130
(1, 1, 0, 0) 239

糟糕!如果你愿意的话,你可以进行正式的卡方检验,但通过检查可以看出两个排列(第一个和最后一个)的可能性是其他四个的两倍。所以输出甚至不是随机的。

为什么?想一想; - )

<强>提示

对于大小为2*M的套牌,第一个M条目全部为0的概率是多少?有两个答案:

  1. 如果M零和M个的所有排列可能相等,则(2*M)-choose-M中的概率为1(选择{{1}位置的方式数1}}零。)

  2. 在函数构造牌组的方式中,M中偶然的机会为1(0和1在每个2**M位置中的可能性相同)。

    < / LI>

    一般来说,M(2*M)-choose-M大得多,因此该函数构造一个以全部零开头的牌组远远超过“它应该”。对于一副52张牌(2**M):

    M == 26

    因此“以26个零开始”的可能性超过应有的700多万倍。酷: - )

    “一次一个”

    那么可以一次正确地选择0或1吗?对!您只需要使用正确的概率:当剩余>>> from math import factorial as f >>> one = f(52) // f(26)**2 >>> two = 2**26 >>> float(one) / two 7389761.998476148 个零被挑选,并且剩余nzero总“卡”时,选择零,概率为nremaining

    nzero / nremaining

    请注意,无需计算。当def deckmaker(n=52): deck = [None] * n nremaining = float(n) nzero = nremaining / 2.0 for i in range(n): if random.random() < nzero / nremaining: deck[i] = 0 nzero -= 1.0 else: deck[i] = 1 nremaining -= 1.0 return deck 变为0.0时,nzero测试将永远不会成功(if不会发生);一旦我们选择random() < 0.0个,n/2将成立,nzero == nremaining测试将始终成功(if始终为真)。它很可爱; - )

答案 1 :(得分:2)

我不确定这是你的意思,但我认为第一种方法生成的最后一张牌不成比例地可能是相同的。

从50个或更少的样本中获得26个或26个零的可能性似乎很大(我认为你可以使用交换二项分布来计算它)。即使很小的机会也意味着你应该赌最后的牌是相同的(因此其他牌是相反的)颜色。

你可以做的只是添加零和一个,直到有52张卡,然后在最后将随机的变为零(或另一种方式),直到每个都有26个。

编辑: 假设牌组有4张牌。前两种颜色是随机的:

25% (0, 0)
25% (0, 1)
25% (1, 0)
25% (1, 1)

但对于(0, 0)(1, 1),最后两张牌已经确定,分别为(1, 1)(0, 0)。其他人需要一个数字来确定结果:

25.0% (0, 0, 1, 1)
12.5% (0, 1, 0) > (0, 1, 0, 1)
12.5% (0, 1, 1) > (0, 1, 1, 0)
12.5% (1, 0, 0) > (1, 0, 0, 1)
12.5% (1, 0, 1) > (1, 0, 1, 0)
25.0% (1, 1, 0, 0)

正如您所看到的,并非所有选项都具有同等可能性。当然,52张卡的差异较小,但这个想法保持不变。