I'm writing a Python function that will recognize a 'straight' from Poker. My code works and will recognize a straight, but only gives me the numbers in the straight, not the suit. Further the rest of the code is written with a specific format for the cards, i.e. python dictionary format, and therefore I need this function to also return the cards in this format.
My code so far:
cards_numbers=[11, 5, 6, 4, 2, 4, 3]
cards_dct={'11D': (11, 'D'), '5S': (5, 'S'), '6S': (6, 'S'), '4D': (4, 'D'), '2H': (2, 'H'), '4C': (4, 'C'), '3D': (3, 'D')}
def is_straight():
straight=False
numbers=set(numbers)
print numbers
sorted_numbers=sorted(numbers)
for i in range(len(sorted_numbers)):
if sorted_numbers[i]-sorted_numbers[i-1]==1 and sorted_numbers[i-1]-sorted_numbers[i-2]==1 and sorted_numbers[i-2]-sorted_numbers[i-3]==1 and sorted_numbers[i-3]-sorted_numbers[i-4]==1:
straight=True
highest_in_straight=sorted_numbers[i]
straight_numbers=range(highest_in_straight-4,highest_in_straight+1)
print straight_numbers
print self.cards_dct
for i in cards_dct.keys():
for j in numbers:
pattern=re.compile(str(j)+'[DSHC]')
print re.findall(pattern,i)
The above code will identify a straight but I'm having difficulty getting back the numbers and the suit from the dictionary. So my question is, how can I get my code to to return a dictionary, containing only elements within the straight (excluding the duplicate 4's) ?
desired_outout={'5S': (5, 'S'), '6S': (6, 'S'), '2H': (2, 'H'), '4C': (4, 'C'), '3D': (3, 'D')}
Like Barmar, I would suggest using a list of dictionaries to represent your hand.
hand = [{'rank':10, 'suit':'Spade'}, {'rank':11, 'suit':'Heart'}, ...]
Then you could check if there's a straight by creating a set of ranks (which will eliminate duplicates). If the difference between the max rank and min rank plus one is equal to the size of the set and the set is the size of the hand, you have a straight. It's a reduction to the pigeonhole principle.
Implementing this in Python is pretty trivial.
Here's to verify it works given a straight:
>>> hand = [{'rank':10, 'suit':'Spade'}, {'rank':11, 'suit':'Heart'}, {'rank':9, 'suit':'Spade'}, {'rank':12, 'suit':'Spade'}, {'rank':8, 'suit':'Spade'}]
>>> rank_set = { card['rank'] for card in hand }
>>> rank_set
set([8, 9, 10, 11, 12])
>>> is_straight = (max(rank_set) - min(rank_set) + 1) == len(hand) and len(rank_set) == len(hand)
>>> is_straight
True
and now to check if it isn't a straight:
>>> hand = [{'rank':10, 'suit':'Spade'}, {'rank':11, 'suit':'Heart'}, {'rank':9, 'suit':'Spade'}, {'rank':12, 'suit':'Spade'}, {'rank':7, 'suit':'Spade'}]
>>> rank_set = { card['rank'] for card in hand }
>>> is_straight = (max(rank_set) - min(rank_set) + 1) == len(hand) and len(rank_set) == len(hand)
>>> is_straight
False
Now to make it a function:
def is_a_straight(hand):
rank_set = { card['rank'] for card in hand }
rank_range = max(rank_set) - min(rank_set) + 1
return rank_range == len(hand) and len(rank_set) == len(hand)
Don't use a dictionary to represent the hand, use a list of lists or a list of dicts, e.g.
cards = [{rank: 5, suit: 'S'}, {rank: 11, suit: 'D'}, ...]
Then your is_straight function can work with this, by sorting it based on the rank element and then testing whether sorted_numbers[i].rank == sorted_numbers[i-1].rank + 1 and so on. When it detects that there's a straight, it can simply use the cards in sorted_cards.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With