尝试打印同花顺的概率

问题描述 投票:0回答:2

我有代码可以不断循环直到刷新为止。现在,我尝试使用计数来显示出处理了多少手,然后除以一的概率。

对于我现在使用count的代码,它返回为0

from collections import namedtuple
from random import shuffle

Card = namedtuple("Card", "suit, rank")

class Deck:
    suits = '♦♥♠♣'
    ranks = '23456789JQKA'

    def __init__(self):
        self.cards = [Card(suit, rank) for suit in self.suits for rank in self.ranks]
        shuffle(self.cards)

    def deal(self, amount):
        return tuple(self.cards.pop() for _ in range(amount))

flush = False
count = 0
while not flush:

    deck = Deck()
    stop = False
    while len(deck.cards) > 5:
        hand = deck.deal(5)
        # (Card(suit='♣', rank='7'), Card(suit='♠', rank='2'), Card(suit='♥', rank='4'), Card(suit='♥', rank='K'), Card(suit='♣', rank='3'))

        if len(set(card.suit for card in hand)) > 1:
            #print(f"No Flush: {hand}")
            continue
        print(f"Yay, it's a Flush: {hand}")
        flush = True
        break
        if flush:
            break
        else:
            count +=1
print(f'Count is {count}')

如果需要,顶部还有一些用于初始化方法的代码让我知道

python poker
2个回答
2
投票

您的代码(以及@Mason答案中的内容)将估计最终刷新first的可能性。为了估计在general中获得冲洗的可能性,我相信这是您所追求的,您必须对该实验进行数千次。在实践中,这称为蒙特卡洛模拟。

旁注:当我开始了解蒙特卡洛斯时,我以为它们是一种“魔术”的,神秘的复杂事物……主要是因为它们的名字听起来如此奇特。不要上当。 “ Monte Carlo”只是一个过于花哨的名称,并且是“模拟”的arbitrary名称。他们可能是非常基础的。

即便如此,仿真还是很神奇的,因为即使很难获得复杂系统的数学模型,也可以使用它们将解决方案强行运出。举例来说,您对组合或排列数学不完全了解,这将为您的问题“获得同花大顺的几率是多少?”]给出确切的答案。我们可以对您的纸牌游戏进行许多模拟,以高度确定这种可能性。我已经在下面完成了(注释掉了原始代码中不需要的部分):

from collections import namedtuple
from random import shuffle
import pandas as pd

#%% What is the likelyhood of getting flush? Mathematical derivation
""" A flush consists of five cards which are all of the same suit.
We must remember that there are four suits each with a total of 13 cards.
Thus a flush is a combination of five cards from a total of 13 of the same suit.
This is done in C(13, 5) = 1287 ways.
Since there are four different suits, there are a total of 4 x 1287 = 5148 flushes possible. 
Some of these flushes have already been counted as higher ranked hands.
We must subtract the number of straight flushes and royal flushes from 5148 in order to
obtain flushes that are not of a higher rank.
There are 36 straight flushes and 4 royal flushes.
We must make sure not to double count these hands.
This means that there are 5148 – 40 = 5108 flushes that are not of a higher rank. 
We can now calculate the probability of a flush as 5108/2,598,960 = 0.1965%.
This probability is approximately 1/509. So in the long run, one out of every 509 hands is a flush."""
"SOURCE: https://www.thoughtco.com/probability-of-a-flush-3126591"

mathematically_derived_flush_probability = 5108/2598960 * 100

#%% What is the likelyhood of getting flush? Monte Carlo derivation

Card = namedtuple("Card", "suit, rank")

class Deck:
    suits = '♦♥♠♣'
    ranks = '23456789JQKA'

    def __init__(self):
        self.cards = [Card(suit, rank) for suit in self.suits for rank in self.ranks]
        shuffle(self.cards)

    def deal(self, amount):
        return tuple(self.cards.pop() for _ in range(amount))

#flush = False
hand_count = 0
flush_count = 0
flush_cutoff = 150 # Increase this number to run the simulation over more hands.
column_names = ['hand_count', 'flush_count', 'flush_probability', 'estimation_error']
hand_results = pd.DataFrame(columns=column_names)

while flush_count < flush_cutoff:
    deck = Deck()
    while len(deck.cards) > 5:
        hand_count +=1
        hand = deck.deal(5)
        # (Card(suit='♣', rank='7'), Card(suit='♠', rank='2'), Card(suit='♥', rank='4'), Card(suit='♥', rank='K'), Card(suit='♣', rank='3'))
        if len(set(card.suit for card in hand)) == 1:
#            print(f"Yay, it's a Flush: {hand}")
            flush_count +=1
#            break
#        else:
#            print(f"No Flush: {hand}")
        monte_carlo_derived_flush_probability = flush_count / hand_count * 100
        estimation_error = (monte_carlo_derived_flush_probability - mathematically_derived_flush_probability) / mathematically_derived_flush_probability * 100
        hand_df = pd.DataFrame([[hand_count,flush_count,monte_carlo_derived_flush_probability, estimation_error]], columns=column_names)
        hand_results = hand_results.append(hand_df)

#%% Analyze results
# Show how each consecutive hand helps us estimate the flush probability
hand_results.plot.line('hand_count','flush_probability').axhline(y=mathematically_derived_flush_probability,color='r')

# As the number of hands (experiments) increases, our estimation of the actual probability gets better.
# Below the error gets closer to 0 percent as the number of hands increases.
hand_results.plot.line('hand_count','estimation_error').axhline(y=0,color='black')

#%% Memory usage
print("Memory used to store all %s runs: %s megabytes" % (len(hand_results),round(hand_results.memory_usage(index=True,deep=True).sum()/1000000, 1)))

在这种情况下,由于数学的原因,我们可以放心地得出将同花的概率设为0.1965%。为了证明我们的模拟得出了正确的答案,我们可以在80,000手之后比较其输出:

enter image description here

您可以看到,我们模拟的flush_probability(蓝色)接近数学得出的概率(黑色)。

类似地,下面是模拟概率与数学推导值之间的estimation_error曲线。如您所见,在模拟的早期运行中,估计误差超过100%,但逐渐上升到误差的5%以内。

enter image description here

[如果您要以两倍于手的数量运行模拟,那么我们将看到蓝线和红线最终与两个图中的黑色水平线重叠-表示模拟答案与数学上相等。得出的答案。

模拟还是不模拟?

最后,您可能会想,

“如果我可以通过模拟问题来产生精确的答案,那么为什么首先要打扰所有复杂的数学?”

答案是,就像对人生中的任何决定一样,“权衡取舍”。

在我们的示例中,我们可以在足够多的双手上运行模拟,从而以高度的置信度获得准确的答案。但是,如果由于他们不知道

答案(通常是这种情况)而正在运行模拟,则需要回答另一个问题,

“我要模拟多长时间才能确信我有正确的答案?”

答案似乎很简单:

“长时间运行。”

最终,您的估计输出可能会收敛为单个值,以使来自其他模拟的输出不会与之前的运行有太大变化。这里的问题是,在某些情况下,根据您要模拟的系统的复杂性,看似收敛的输出可能只是暂时现象。也就是说,如果您再进行十万次仿真,您可能会开始发现您的输出与您认为的稳定答案有所不同。在不同的情况下,尽管已经运行了数千万次仿真,但是可能仍然没有收敛输出。您有时间编程和运行仿真吗?还是数学上的近似值能使您早日到达那里?

还有另一个问题:

*“费用是多少?”

消费计算机今天相对便宜,但30年前,它们的成本$4,000 to $9,000以2019年美元计算。相比之下,TI89 only cost $215(同样以2019年美元计)。因此,如果您在1990年问这个问题,并且您对概率数学很满意,那么使用TI89可以节省3,800美元。今天的成本同样重要:模拟self-driving汽车和protein folding可以燃烧数百万美元。

最后,关键任务应用程序可能需要仿真和数学模型来交叉检查两种方法的结果。一个很好的例子是,StandUpMaths的Matt Parker通过模拟计算得出the odds of landing on any property in the game of Monopoly,并用汉娜·弗莱的同一款游戏的数学模型确认了这些结果。


2
投票

我认为这应该对您有用。我想这取决于Deck()的定义。我试图使您的代码处于与编写代码相似的状态,但是必须进行一些更改,以免出现错误。我也没有实际运行它,因为我没有定义Deck

© www.soinside.com 2019 - 2024. All rights reserved.