Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Identifying a 'straight' (from Poker) using Python

Tags:

python

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 image 812
CiaranWelsh Avatar asked Dec 04 '25 23:12

CiaranWelsh


2 Answers

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)
like image 108
erip Avatar answered Dec 07 '25 15:12

erip


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.

like image 43
Barmar Avatar answered Dec 07 '25 15:12

Barmar