如何用sympy表示一副纸牌?

时间:2019-01-14 18:40:08

标签: sympy

Sympy具有DieCoin对象,它们对于理解概率概念非常有用。例如

from sympy.stats import P, Die, density
from sympy import Eq

D = Die('D', 6)
density(D).dict
# {1: 1/6, 2: 1/6, 3: 1/6, 4: 1/6, 5: 1/6, 6: 1/6}

P(D > 3)
# 1/2

我希望能够使用一副纸牌进行类似的计算,例如

deck = DeckOfCards('Cards')
P(Eq(deck, 'AceOfSpades'))
# 1/52

如何用sympy做到这一点?我猜一个选择是

deck = DiscreteUniform('Cards', list(range(52)))

def lookup_card_id(name):

   # encode the list, e.g.
   # 0 = Ace of Clubs
   # 1 = 2 of Clubs
   # 2 = 3 of Clubs
   # and so on ...

   return card_id

P(Eq(deck, lookup_card_id('AceOfClubs'))
# 1/52

这将使我走到现在,但它不支持以下查询:

P(Eq(deck, lookup_card_id('Ace'))
# 1/13

1 个答案:

答案 0 :(得分:1)

不幸的是DiscreteUniform似乎无法处理类似的情况

P(Eq(deck, [0, 1, 2]))
or
P(deck in [0, 1, 2])

但是你可以自己做。

from sympy import Eq
from sympy.stats import P, DiscreteUniform

suits = ('Clubs', 'Diamonds', 'Hearts', 'Spades')
numbers = ('Ace', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King')
colors = {
    'Black': ['Clubs', 'Spades'],
    'Red': ['Diamonds', 'Hearts']
}

def get_card_name(suit, number):
    return '{number}Of{suit}'.format(number=number, suit=suit)

cards = {}
for sidx, suit in enumerate(suits):
    for nidx, number in enumerate(numbers):
        name = get_card_name(suit, number)
        cards[name] = sidx * 13 + (nidx + 1)

def flatten(list):
    return reduce(lambda l, l2: l + l2, list, [])

def lookup_card_id(names):
    if isinstance(names, list) or isinstance(names, tuple):
        return flatten([lookup_card_id(x) for x in names])
    if names in suits:
        names_in_suits = [get_card_name(names, x) for x in numbers]
        return lookup_card_id(names_in_suits)
    if names in numbers:
        names_in_numbers = [get_card_name(x, names) for x in suits]
        return lookup_card_id(names_in_numbers)
    if names in colors:
        return lookup_card_id(colors[names])
    return [cards[names]]

def prob_pick_card(name):
    deck = DiscreteUniform('Cards', list(range(1, 53)))
    card_id = lookup_card_id(name)
    return sum([P(Eq(deck, x)) for x in card_id])

print(prob_pick_card('AceOfClubs')) # 1/52
print(prob_pick_card('Ace')) # 1/13
print(prob_pick_card('Clubs')) # 1/4
print(prob_pick_card('Black')) # 1/2