advent-of-code/2023/python/day07.py
2023-12-08 13:42:42 -05:00

99 lines
2.2 KiB
Python

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()