Reputation: 12817
I have a list of tuples representing playing cards: hand = [('A', '♣'), ('A', '♠'), ('A', '♦'), ('A', '♥'), ('K', '♠')]
and I want to check if I have a flush.
I thought of using all(h[1] == '♠' for h in hand)
and it seems to work well (False
in this case, but True
in others, where it should. Of course I'll need to check this for all 4 suits...), but I wanted to know if this is the right/best way to do so
Upvotes: 0
Views: 63
Reputation: 1028
To add onto Ofer Sadans answer, i would suggest using flags to represent cards, since computers are easier for integer to calculate value via bitwise operators
than unicode string manipulation.
This solution would need some sort of conversion from tuple type to integer representation but it is possible with simple lambda function.
card = ('K','\u2660') # for example. K ♠
card_pack = lambda c: (ord(c[0])<<16)+ord(c[1]) #c for card
# where you have now 32 bit integer that contains all your values
# 00000000-01001011|00100110-01100000 == 4 925 024
# KING | SPADE
With this version you can ( as long you have finite number of cards in a hand ) make a hand long integer
and check a hand as a whole. With premade masks
you can easily check for all decks and values with single ==
logical operator.
hand = [('A', u'\u2663'), ('A', u'\u2660'), ('A', u'\u2666'), ('A', u'\u2665'), ('K', u'\u2660')]
hand_i = map( card_pack, hand )
hand_i = sum( [ val<<( shift*32 ) shift,val in enumerate(hand_i) ] )
Then if you need you can unpack each card with unpacking
function:
card_unpack = lambda ci: ( (ci>>16)&0xffff, ci&0xffff) #ci for card integer
unpack_2_individual_cards = lambda hand_i,_i: (hand_i>>(32*_i))&0xffffffff
# then you just need to do similar function as summing for hand_i but inverse to get each card individual and use unichr/chr to represent values after that.
hand = [ unpack_2_individual_cards(hand_i, i ) for i in range(5) ]
And then the test for strength of hand or what type of hand it is would be easy as :
STRAIGHT = 1675898824200706064573121072408259537242498659
if hand_i&STRAIGHT==STRAIGHT: print('you have straight')
if hand_i < STRAIGHT: print('straight wins!!')
Have in mind that any logical operation ( with all
and any
) use this same approach on finding logical relationships between elements. It is just that this type of approach is so low level that it is under the surface. The type of data that we compare is to us as programmers , but to computer it is all the same as long as we tell it where to find it.
You can use struct
module for packing and unpacking the data instead of those lambdas
and you can check the specific type of deck in hand with simple mask of 0x00ff00ff00ff00ff00ff
and values in hand with 0xff00ff00ff00ff00ff00
since all cards are packed by value|deck
.
Upvotes: 0
Reputation: 11922
You could:
any(all(h[1] == suit for h in hand) for suit in ('♣','♠','♦','♥'))
Which isn't very efficient but very readable in my opinion or you could do as suggested by @ Ev. Kounis in the comments, which is much more efficient solution but not very readable. Since this game only has 52 cards per deck, 4 suits, 13 sets, and 5 cards per hand, the numbers aren't so large that they require any special treatment for efficiency, so I would go with this solution.
Upvotes: 1