Skip to content

Instantly share code, notes, and snippets.

@peverett
Created December 7, 2017 14:31
Show Gist options
  • Save peverett/5cb1508edca259091ec162e5e2d04c1a to your computer and use it in GitHub Desktop.
Save peverett/5cb1508edca259091ec162e5e2d04c1a to your computer and use it in GitHub Desktop.
#!/usr/python
"""
A famous casino is suddenly faced with a sharp decline of their revenues. They
decide to offer Texas hold'em also online. Can you help them by writing an
algorithm that can rank poker hands?
Task:
Create a poker hand that has a method to compare itself to another poker hand:
compare_with(self, other_hand)
A poker hand has a constructor that accepts a string containing 5 cards:
PokerHand(hand)
The characteristics of the string of cards are:
* A space is used as card seperator
* Each card consists of two characters
* The first character is the value of the card, valid characters are:
2, 3, 4, 5, 6, 7, 8, 9, T(en), J(ack), Q(ueen), K(ing), A(ce)
* The second character represents the suit, valid characters are:
* S(pades), H(earts), D(iamonds), C(lubs)
The result of your poker hand compare can be one of these 3 options:
RESULT = ["Loss", "Tie", "Win"]
Apply the Texas Hold'em rules for ranking the cards.
There is no ranking for the suits.
https://www.briggsoft.com/docs/pmavens/PMHoldem.htm
"""
class PokerHand(object):
"""Design
The type of hand is given a score, according to what hand beats what.
The score of the cards IN that hand is calculated, so that hands of the
same time can be compared.
Whatever cards are left are also scored in the case of everything being
equal e.g. two hands with a pair being the same pair - who wins!
"""
LOSS = "Loss"
TIE = "Tie"
WIN = "Win"
value_map = {
'1': 1, '2': 2, '3': 3, '4': 4,
'5': 5, '6': 6, '7': 7, '8': 8,
'9': 9, 'T': 10, 'J': 11, 'Q': 12,
'K': 13, 'A': 14
}
def __init__(self, hand):
self.hand = hand.strip().split()
self.values = [PokerHand.value_map[card[0]] for card in self.hand]
self.values.sort()
self.counts = {value: self.values.count(value) for value in self.values}
self.card_score = sum(self.values)
self.hand_score = self.score_hand()
def is_flush(self):
suit = [card[1] for card in self.hand]
return (suit.count(suit[0]) == 5)
def is_straight(self):
for index in range(1,5):
if self.values[index-1] + 1 != self.values[index]:
return False
return True
def is_four_of_kind(self):
return (4 in self.counts.values())
def is_full_house(self):
return (2 in self.counts.values() and 3 in self.counts.values())
def is_three_of_kind(self):
return (3 in self.counts.values())
def is_two_pair(self):
return (self.counts.values().count(2) == 2)
def is_pair(self):
return (self.counts.values().count(2) == 1)
def score_hand(self):
if self.is_straight() and self.is_flush():
return 8
elif self.is_four_of_kind():
return 7
elif self.is_full_house():
return 6
elif self.is_flush():
return 5
elif self.is_straight():
return 4
elif self.is_three_of_kind():
return 3
elif self.is_two_pair():
return 2
elif self.is_pair():
return 1
else:
return 0
def compare_with(self, other):
print "\nhand", self.hand, " - ", other.hand
print "values ", self.values, " - ", other.values
print "counts ", self.counts, " - ", other.counts
print "card score ", self.card_score, " - ", other.card_score
print "hand_score ", self.hand_score, " - ", other.hand_score
if self.hand_score > other.hand_score:
return self.WIN
elif self.hand_score < other.hand_score:
return self.LOSS
else:
if self.card_score > other.card_score:
return self.WIN
elif self.card_score < other.card_score:
return self.LOSS
return self.TIE
class TestPokerHands(object):
def runTest(self, expected, hand, other):
player = PokerHand(hand)
opponent = PokerHand(other)
assert player.compare_with(opponent) == expected
def test_highest_flush(self):
"Highest straight flush wins"
self.runTest("Loss", "2H 3H 4H 5H 6H", "KS AS TS QS JS")
def test_straight_flush(self):
"Straight flush wins of 4 of a kind"
self.runTest("Win", "2H 3H 4H 5H 6H", "AS AD AC AH JD")
def test_highest_4_of_a_kind(self):
"Highest 4 of a kind wins"
self.runTest("Win", "AS AH 2H AD AC", "JS JD JC JH 3D")
def test_4oak_over_fh(self):
"4 Of a kind wins of full house"
self.runTest("Loss", "2S AH 2H AS AC", "JS JD JC JH AD")
def test_fh_over_flush(self):
"Full house wins of flush"
self.runTest("Win", "2S AH 2H AS AC", "2H 3H 5H 6H 7H")
def test_highest_flush(self):
"Highest flush wins"
self.runTest("Win", "AS 3S 4S 8S 2S", "2H 3H 5H 6H 7H")
def test_flush_over_straight(self):
"Flush wins of straight"
self.runTest("Win", "2H 3H 5H 6H 7H", "2S 3H 4H 5S 6C")
def test_equal_straight(self):
"Equal straight is tie"
self.runTest("Tie", "2S 3H 4H 5S 6C", "3D 4C 5H 6H 2S")
def test_straight_over_3oak(self):
"Straight wins of three of a kind"
self.runTest("Win", "2S 3H 4H 5S 6C", "AH AC 5H 6H AS")
def test_3oak_over_2pair(self):
"3 Of a kind wins of two pair"
self.runTest("Loss", "2S 2H 4H 5S 4C", "AH AC 5H 6H AS")
def test_2pair_over_pair(self):
"2 Pair wins of pair"
self.runTest("Win", "2S 2H 4H 5S 4C", "AH AC 5H 6H 7S")
def test_highest_pair(self):
"Highest pair wins"
self.runTest("Loss", "6S AD 7H 4S AS", "AH AC 5H 6H 7S")
def test_pair_over_nothing(self):
"Pair wins of nothing"
self.runTest("Loss", "2S AH 4H 5S KC", "AH AC 5H 6H 7S")
def test_highest_card_loses(self):
"Highest card loses"
self.runTest("Loss", "2S 3H 6H 7S 9C", "7H 3C TH 6H 9S")
def test_highest_card_wins(self):
"Highest card wins"
self.runTest("Win", "4S 5H 6H TS AC", "3S 5H 6H TS AC")
def test_qual_cards_tie(self):
"Equal cards is tie"
self.runTest("Tie", "2S AH 4H 5S 6C", "AD 4C 5H 6H 2C")
def test_3oak_highest_wins(self):
"3 of Kind highest Win wins"
# Even though the 'other' hand has a higher 3 of a kind
# It loses when just comparing the card score, which is wrong
self.runTest("Loss", "2S 2H 2D AC KC", "3S 3S 3C 2S 4S")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment