from __future__ import annotations from enum import Enum from collections import defaultdict from functools import reduce from .aoc import AocParseLinesSameParser, Aoc2 class Type(Enum): HIGH_CARD = 0 ONE_PAIR = 1 TWO_PAIR = 2 THREE_KIND = 3 FULL_HOUSE = 4 FOUR_KIND = 5 FIVE_KIND = 6 def __lt__(self, other: Type) -> bool: return self.value < other.value class Hand2: def __init__(self, string: str) -> None: translation = "J23456789TQKA" self.string = [translation.index(x) for x in string] self.cards_dict = defaultdict(lambda : 0) for letter in string: self.cards_dict[letter] += 1 value_amount = list(reversed(sorted(list([v for k, v in self.cards_dict.items() if k !="J"])))) joker_amount = self.cards_dict["J"] if joker_amount == 5: self.type = Type.FIVE_KIND return match value_amount[0] + joker_amount: case 5: self.type = Type.FIVE_KIND case 4: self.type = Type.FOUR_KIND case 3: if value_amount[1] == 2: self.type = Type.FULL_HOUSE else: self.type = Type.THREE_KIND case 2: if value_amount[1] == 2: self.type = Type.TWO_PAIR else: self.type = Type.ONE_PAIR case _: self.type = Type.HIGH_CARD def __lt__(self, other: Hand) -> bool: """ self < other """ return (self.type, self.string) < (other.type, other.string) def __repr__(self) -> str: return f"Hand({self.type}, {self.string})" class Hand: def __init__(self, string: str) -> None: translation = "23456789TJQKA" self.string = [translation.index(x) for x in string] self.cards_dict = defaultdict(lambda : 0) for letter in string: self.cards_dict[letter] += 1 value_amount = list(reversed(sorted(list(self.cards_dict.values())))) match value_amount[0]: case 5: self.type = Type.FIVE_KIND case 4: self.type = Type.FOUR_KIND case 3: if value_amount[1] == 2: self.type = Type.FULL_HOUSE else: self.type = Type.THREE_KIND case 2: if value_amount[1] == 2: self.type = Type.TWO_PAIR else: self.type = Type.ONE_PAIR case _: self.type = Type.HIGH_CARD def __lt__(self, other: Hand) -> bool: """ self < other """ return (self.type, self.string) < (other.type, other.string) def __repr__(self) -> str: return f"Hand({self.type}, {self.string})" # class Day07(AocParseLinesSameParser[tuple[Hand, int]], Aoc2[list[tuple[Hand, int]], list[tuple[Hand, int]]]): class Day07(Aoc2[list[tuple[Hand, int]], list[tuple[Hand2, int]]]): def parseinput1(self, inpt: str) -> list[tuple[Hand, int]]: lines = inpt.splitlines() return [(Hand(line.split(" ")[0]), int(line.split(" ")[1])) for line in lines] def parseinput2(self, inpt: str) -> list[tuple[Hand2, int]]: lines = inpt.splitlines() return [(Hand2(line.split(" ")[0]), int(line.split(" ")[1])) for line in lines] def part1(self, inpt: list[tuple[Hand, int]]) -> int: return sum(((rnk + 1) * bid) for rnk, (_, bid) in list(enumerate(sorted(inpt)))) def part2(self, inpt: list[tuple[Hand2, int]]) -> int: return sum(((rnk + 1) * bid) for rnk, (_, bid) in list(enumerate(sorted(inpt)))) def main() -> None: day07 = Day07(2023, 7) day07.run() if __name__ == "__main__": main()