from __future__ import annotations from typing import Optional, TypeAlias from dataclasses import dataclass, field from .aoc import Aoc2 P1: TypeAlias = list[str] P2: TypeAlias = list[tuple[str, Optional[int]]] class Day15(Aoc2[P1, P2]): def parseinput1(self, inpt: str) -> P1: inpt = "".join(inpt.splitlines()) return inpt.split(",") def parseinput2(self, inpt: str) -> P2: inpt = "".join(inpt.splitlines()) output = [] for word in inpt.split(","): if "-" in word: output.append((word[:-1], None)) else: name, boxnr = word.split("=") output.append((name, int(boxnr))) return output @staticmethod def hash(string: str) -> int: waccum = 0 for char in string: waccum += ord(char) waccum *= 17 waccum = waccum % 256 return waccum def part1(self, inpt: P1) -> int: accum = 0 for word in inpt: accum += self.hash(word) return accum def part2(self, inpt: P2) -> int: boxes = {} for name, op in inpt: boxnr = self.hash(name) if boxnr not in boxes: boxes[boxnr] = {} if op is None: if name in boxes[boxnr]: del boxes[boxnr][name] else: boxes[boxnr][name] = op accum = 0 for nr, box in boxes.items(): for pos, (label, lens) in enumerate(box.items()): fp = (1 + nr) * (1 + pos) * lens accum += fp return accum def main() -> None: aoc = Day15(2023, 15, example_code_nr2=0) aoc.run() if __name__ == "__main__": main()