Skip to content

Instantly share code, notes, and snippets.

@Mellen
Last active January 4, 2023 11:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mellen/a2b8632605f71942238ae025cb7d9ca9 to your computer and use it in GitHub Desktop.
Save Mellen/a2b8632605f71942238ae025cb7d9ca9 to your computer and use it in GitHub Desktop.
Rank poker hands.
VALUE_ORDER = ['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A']
class PokerHand:
def __init__(self, cards):
self.cards = []
self.rankName = ''
self.original = cards
for card_str in cards:
self.cards.append(Card(card_str.upper()))
self.highest = self.cards[0]
self.multiHigh = None
self.lowPair = None
self.cards.sort()
self.highest = self.cards[-1]
def __str__(self):
return ' '.join(self.original)
def isRoyalFlush(self):
if self.isFlush():
return ''.join([card.value for card in self.cards]) == 'TJQKA'
else:
return False
def isStraightFlush(self):
if self.isFlush():
return self.isStraight()
else:
return False
def isFourOfAKind(self):
isTrue, value = self.isNOfAKind(4)
self.multiHigh = value
return isTrue
def isFullHouse(self):
last_card = self.cards[0]
triple = False
pair = False
count = 1
for card in self.cards[1:]:
if card.value == last_card.value:
count += 1
else:
if count == 2:
pair = True
elif count == 3:
triple = True
self.multiHigh = last_card
count = 1
last_card = card
if count == 2:
pair = True
elif count == 3:
triple = True
self.multiHigh = last_card
return triple and pair
def isStraight(self):
last_index = VALUE_ORDER.index(self.cards[0].value)
for card in self.cards[1:]:
index = VALUE_ORDER.index(card.value)
if index != last_index + 1:
return False
last_index = index
return True
def isFlush(self):
suit = self.cards[0].suit
for card in self.cards[1:]:
if card.suit != suit:
return False
return True
def isThreeOfAKind(self):
isTrue, value = self.isNOfAKind(3)
self.multiHigh = value
return isTrue
def isTwoPair(self):
pair1 = False
pair2 = False
last_card = self.cards[0]
count = 1
for card in self.cards[1:]:
if card.value == last_card.value:
count += 1
else:
if count == 2 and not pair1:
pair1 = True
self.multiHigh = last_card
elif count == 2 and pair1:
if last_card > self.multiHigh:
self.lowPair = self.multiHigh
self.multiHigh = last_card
else:
self.lowPair = last_card
pair2 = True
count = 1
last_card = card
if count == 2 and pair1:
if last_card > self.multiHigh:
self.lowPair = self.multiHigh
self.multiHigh = last_card
else:
self.lowPair = last_card
pair2 = True
return pair1 and pair2
def isAPair(self):
isTrue, value = self.isNOfAKind(2)
self.multiHigh = value
return isTrue
def isNOfAKind(self, n):
count = 1
high_count = 1
last_card = self.cards[0]
value = last_card
for card in self.cards[1:]:
if card.value == last_card.value:
count += 1
value = last_card
else:
if count > high_count:
high_count = count
count = 1
last_card = card
if count > high_count:
high_count = count
return (high_count == n, value)
def getRank(self):
rank = 10
if self.isRoyalFlush():
self.rankName = 'Royal Flush'
rank = 1
elif self.isStraightFlush():
self.rankName = 'Straight Flush'
rank = 2
elif self.isFourOfAKind():
self.rankName = 'Four of a Kind'
rank = 3
elif self.isFullHouse():
self.rankName = 'Full House'
rank = 4
elif self.isFlush():
self.rankName = 'Flush'
rank = 5
elif self.isStraight():
self.rankName = 'Straight'
rank = 6
elif self.isThreeOfAKind():
self.rankName = 'Three of a Kind'
rank = 7
elif self.isTwoPair():
self.rankName = 'Two Pair'
rank = 8
elif self.isAPair():
self.rankName = 'Pair'
rank = 9
if rank > 1 and rank < 10:
self.rankName = f'{self.highest.value} High {self.rankName}'
elif rank == 10:
self.rankName = f'{self.highest.value} High'
return rank
def compareWith(self, other):
leftRank = self.getRank()
rightRank = other.getRank()
if leftRank < rightRank:
return f'{self} ({self.rankName}) beats {other} ({other.rankName})'
elif rightRank < leftRank:
return f'{self} ({self.rankName}) loses to {other} ({other.rankName})'
else:
if leftRank == 1:
return f'{self} ({self.rankName}) draws with {other} ({other.rankName})'
elif leftRank == 2 or leftRank == 5 or leftRank == 6 or leftRank == 10:
if self.highest > other.highest:
return f'{self} ({self.rankName}) beats {other} ({other.rankName})'
elif self.highest < other.highest:
return f'{self} ({self.rankName}) loses to {other} ({other.rankName})'
else:
return f'{self} ({self.rankName}) draws with {other} ({other.rankName})'
elif leftRank == 3 or leftRank == 4 or leftRank == 7 or leftRank == 9:
if self.multiHigh > other.multiHigh:
return f'{self} ({self.rankName}) beats {other} ({other.rankName})'
elif self.multiHigh < other.multiHigh:
return f'{self} ({self.rankName}) loses to {other} ({other.rankName})'
elif leftRank == 9:
if self.highest > other.highest:
return f'{self} ({self.rankName}) beats {other} ({other.rankName})'
elif self.highest < other.highest:
return f'{self} ({self.rankName}) loses to {other} ({other.rankName})'
else:
return f'{self} ({self.rankName}) draws with {other} ({other.rankName})'
else:
return f'{self} ({self.rankName}) draws with {other} ({other.rankName})'
elif leftRank == 8:
if self.multiHigh > other.multiHigh:
return f'{self} ({self.rankName}) beats {other} ({other.rankName})'
elif self.multiHigh < other.multiHigh:
return f'{self} ({self.rankName}) loses to {other} ({other.rankName})'
else:
if self.lowPair > other.lowPair:
return f'{self} ({self.rankName}) beats {other} ({other.rankName})'
elif self.lowPair < other.lowPair:
return f'{self} ({self.rankName}) loses to {other} ({other.rankName})'
else:
if self.highest > other.highest:
return f'{self} ({self.rankName}) beats {other} ({other.rankName})'
elif self.highest < other.highest:
return f'{self} ({self.rankName}) loses to {other} ({other.rankName})'
else:
return f'{self} ({self.rankName}) draws with {other} ({other.rankName})'
class Card:
def __init__(self, card_str):
self.value, self.suit = list(card_str)
def __lt__(self, other):
return VALUE_ORDER.index(self.value) < VALUE_ORDER.index(other.value)
def __gt__(self, other):
return VALUE_ORDER.index(self.value) > VALUE_ORDER.index(other.value)
def __eq__(self, other):
return VALUE_ORDER.index(self.value) == VALUE_ORDER.index(other.value)
def __le__(self, other):
return VALUE_ORDER.index(self.value) <= VALUE_ORDER.index(other.value)
def __ge__(self, other):
return VALUE_ORDER.index(self.value) >= VALUE_ORDER.index(other.value)
def __ne__(self, other):
return VALUE_ORDER.index(self.value) != VALUE_ORDER.index(other.value)
import argparse
from poker import PokerHand
parser = argparse.ArgumentParser(description='rank two poker hands')
parser.add_argument('lefthand', nargs=5, help='The cards in the left hand')
parser.add_argument('righthand', nargs=5, help='The cards in the right hand')
def rank(lefthand, righthand):
LH = PokerHand(lefthand)
RH = PokerHand(righthand)
print(LH.compareWith(RH))
if __name__ == '__main__':
args = parser.parse_args()
rank(args.lefthand, args.righthand)
@Mellen
Copy link
Author

Mellen commented Jun 16, 2020

Doesn't work with low ace straights

@miketalbot
Copy link

Think they were counted out in the example anyway :) I thought so when I coded my solution based on the challenge description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment