import matrix import shared from dataclasses import dataclass from collections import defaultdict from pprint import pprint from typing import List # STRENGTHS = list(reversed("A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, 2".split(", "))) STRENGTHS = "A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, 2".split(", ") STRENGTHS_TO_WEIGHT = {k: idx for idx, k in enumerate(STRENGTHS)} STRENGTH_HANDS = [ "Five of a Kind", "Four of a Kind", "Full House", "Three of a Kind", "Two Pair", "One Pair", "High Card", ] def determine_hand(cards): card_set = set(cards) if len(card_set) == 1: return "Five of a Kind" same_cards = sorted([cards.count(a) for a in card_set]) if len(same_cards) == 2: if max(same_cards) == 4: return "Four of a Kind" elif max(same_cards) == 3: return "Full House" elif len(same_cards) == 3: if max(same_cards) == 3: return "Three of a Kind" else: return "Two Pair" elif len(same_cards) == 4: return "One Pair" return "High Card" @dataclass class Hand: cards: str bid: int def counts(self): return Counter(self.cards) def kind(self): cards = [c for c in self.cards] return determine_hand(self.cards) def sort_cards(self): return [STRENGTHS_TO_WEIGHT[x] for x in self.cards] def __lt__(self, other): return self.sort_cards() > other.sort_cards() # @shared.profile def part1(rows): hands = defaultdict(list) for row in rows: cards, bid = row.split() hand = Hand(cards=cards, bid=int(bid)) hands[hand.kind()].append(hand) hands[hand.kind()] = list(sorted(hands[hand.kind()])) in_order = [] for kind in reversed(STRENGTH_HANDS): in_order.extend(hands[kind]) total = 0 for rank, card in enumerate(in_order): total += (rank + 1) * card.bid print(total) # @shared.profile def part2(rows): pass def main(): rows = [row for row in shared.load_rows(7)] with shared.elapsed_timer() as elapsed: part1(rows) print("🕒", elapsed()) with shared.elapsed_timer() as elapsed: part2(rows) print("🕒", elapsed()) if __name__ == "__main__": main()