from typing import List from dataclasses import dataclass card_order = ["A", "K", "Q", "J", "T", "9", "8", "7", "6", "5", "4", "3", "2"] @dataclass class Card: card: str def __lt__(self, other): return card_order.index(self.card) > card_order.index(other.card) def __eq__(self, other): return self.card == other.card def __ne__(self, other): return not self.__eq__(other) def __ge__(self, other): return not self.__lt__(other) def __gt__(self, other): return not self.__lt__(other) and self.__ne__(other) def __le__(self, other): return not self.__gt__(other) @dataclass(init=False,eq=False) class Hand: cards: List[Card] bid: int def __init__(self, cards:str, bid: str): self.bid = int(bid) self.cards = [] for card in cards: self.cards.append(Card(card=card)) def _is_five_of_a_kind(self): return all(map(lambda c: c == self.cards[0], self.cards[1:])) def _is_four_of_a_kind(self): poss1 = list(filter(None, map(lambda c: c == self.cards[0], self.cards[0:]))) poss2 = list(filter(None, map(lambda c: c == self.cards[1], self.cards[0:]))) return len(poss1) == 4 or len(poss2) == 4 def _is_full_house(self): if not self._is_three_of_a_kind: return False if self.cards[0] != self.cards[1]: c1 = list(filter(None, map(lambda c: c == self.cards[0], self.cards[0:]))) c2 = list(filter(None, map(lambda c: c == self.cards[1], self.cards[0:]))) return (len(c1) == 3 and len(c2) == 2) or (len(c1) == 2 and len(c2) == 3) if self.cards[0] == self.cards[1] and self.cards[0] != self.cards[2]: c1 = list(filter(None, map(lambda c: c == self.cards[0], self.cards[0:]))) c3 = list(filter(None, map(lambda c: c == self.cards[2], self.cards[0:]))) return (len(c1) == 3 and len(c3) == 2) or (len(c1) == 2 and len(c3) == 3) if self.cards[0] == self.cards[1] and self.cards[0] == self.cards[2]: return self.cards[3] == self.cards[4] return False def _is_three_of_a_kind(self): poss1 = list(filter(None, map(lambda c: c == self.cards[0], self.cards[0:]))) poss2 = list(filter(None, map(lambda c: c == self.cards[1], self.cards[0:]))) poss3 = list(filter(None, map(lambda c: c == self.cards[2], self.cards[0:]))) return len(poss1) == 3 or len(poss2) == 3 or len(poss3) == 3 def _count_pairs(self): sorted_cards = sorted(self.cards) pairs = 0 for i in range(0, 4): if sorted_cards[i] == sorted_cards[i + 1]: pairs += 1 return pairs def _is_two_pair(self): pairs = self._count_pairs() return pairs == 2 def _is_one_pair(self): pairs = self._count_pairs() return pairs == 1 def highest_card(self): return max(self.cards) def _rank(self): if self._is_five_of_a_kind(): return 6 if self._is_four_of_a_kind(): return 5 if self._is_full_house(): return 4 if self._is_three_of_a_kind(): return 3 if self._is_two_pair(): return 2 if self._is_one_pair(): return 1 return 0 def __lt__(self, other): if self._rank() < other._rank(): return True if self._rank() == other._rank(): for i in range(5): if self.cards[i] < other.cards[i]: return True if self.cards[i] > other.cards[i]: return False return False def __eq__(self, other): return all([self.cards[i] == other.cards[i] for i in range(len(self.cards))]) def __ne__(self, other): return not self.__eq__(other) def __ge__(self, other): return not self.__lt__(other) def __gt__(self, other): return not self.__lt__(other) and self.__ne__(other) def __le__(self, other): return not self.__gt__(other)