diff --git a/aoc/day07.py b/aoc/day07.py index e47e44c..dae1e32 100644 --- a/aoc/day07.py +++ b/aoc/day07.py @@ -31,8 +31,7 @@ class Hand: value_amount = list( reversed( - sorted( - list([v for k, v in self.cards_dict.items() if k != joker])) + sorted(list([v for k, v in self.cards_dict.items() if k != joker])) ) ) joker_amount = 0 @@ -73,16 +72,14 @@ class Day07(Aoc2[list[tuple[Hand, int]], list[tuple[Hand, int]]]): def parseinput1(self, inpt: str) -> list[tuple[Hand, int]]: lines = inpt.splitlines() return [ - (Hand(line.split(" ")[0], "23456789TJQKA"), - int(line.split(" ")[1])) + (Hand(line.split(" ")[0], "23456789TJQKA"), int(line.split(" ")[1])) for line in lines ] def parseinput2(self, inpt: str) -> list[tuple[Hand, int]]: lines = inpt.splitlines() return [ - (Hand(line.split(" ")[0], "J23456789TQKA", "J"), int( - line.split(" ")[1])) + (Hand(line.split(" ")[0], "J23456789TQKA", "J"), int(line.split(" ")[1])) for line in lines ] diff --git a/aoc/day08.py b/aoc/day08.py index bc5a2b7..b9caef3 100644 --- a/aoc/day08.py +++ b/aoc/day08.py @@ -1,4 +1,5 @@ from __future__ import annotations +from dataclasses import dataclass import itertools import math from typing import Optional @@ -6,18 +7,23 @@ from typing import Optional from .aoc import Aoc2, AocSameParser +@dataclass class Map: - def __init__(self, inpt: str) -> None: + directions: list[int] + rules: dict[str, tuple[str, str]] + + @staticmethod + def from_input(inpt: str) -> Map: lines = inpt.splitlines() - self.directions: list[int] = [0 if rl == "L" else 1 for rl in lines[0]] - - self.rules = {line[:3]: (line[7:10], line[12:15]) for line in lines[2:]} + directions: list[int] = [0 if rl == "L" else 1 for rl in lines[0]] + rules = {line[:3]: (line[7:10], line[12:15]) for line in lines[2:]} + return Map(directions, rules) class Day08(AocSameParser[Map], Aoc2[Map, Map]): def parseinput(self, inpt: str) -> Map: - return Map(inpt) + return Map.from_input(inpt) def part1(self, inpt: Map) -> int: current = "AAA" @@ -25,21 +31,20 @@ class Day08(AocSameParser[Map], Aoc2[Map, Map]): for steps, direction in enumerate(itertools.cycle(inpt.directions)): if current == "ZZZ": return steps - else: - current = inpt.rules[current][direction] + current = inpt.rules[current][direction] raise RuntimeError("End of the rainbow") def find_loop(self, list_of_nrs: list[int]) -> Optional[tuple[int, int]]: - for index in range(len(list_of_nrs)): - for index in range(len(list_of_nrs[index + 1 :])): - diff = list_of_nrs[index + 1] - list_of_nrs[index] - if list_of_nrs[index + 1] + diff in list_of_nrs: - return list_of_nrs[index], diff + for index, nr in enumerate(list_of_nrs): + for nr2 in list_of_nrs[index + 1 :]: + diff = nr2 - nr + if nr2 + diff in list_of_nrs: + return nr, diff return None def part2(self, inpt: Map) -> int: current = [node for node in inpt.rules.keys() if node.endswith("A")] - steps_to_z = [[] for _ in current] + steps_to_z: list[list[int]] = [[] for _ in current] loops: list[Optional[tuple[int, int]]] = [None for _ in current] for steps, direction in enumerate(itertools.cycle(inpt.directions)): @@ -50,17 +55,14 @@ class Day08(AocSameParser[Map], Aoc2[Map, Map]): if not any(loop is None for loop in loops): break - else: - current = [inpt.rules[node][direction] for node in current] + current = [inpt.rules[node][direction] for node in current] # Turns out, each path directly loops :/ return math.lcm(*(loop[0] for loop in loops if loop is not None)) def main() -> None: - day08 = Day08(2023, 8) - day08._example_code_nr1 = 1 - day08._example_code_nr2 = -1 + day08 = Day08(2023, 8, example_code_nr1=1, example_code_nr2=-1) day08.run() diff --git a/aoc/day09.py b/aoc/day09.py new file mode 100644 index 0000000..d5e47d1 --- /dev/null +++ b/aoc/day09.py @@ -0,0 +1,38 @@ +from functools import reduce +from typing import Iterable + +from .aoc import Aoc2, AocParseLinesSameParser + + +class Day09(AocParseLinesSameParser[list[int]], Aoc2[list[list[int]], list[list[int]]]): + def parseline(self, inpt: str) -> list[int]: + return [int(d) for d in inpt.split(" ")] + + def derive(self, init: list[int]) -> list[int]: + return [y - x for x, y in zip(init, init[1:])] + + def get_nth_value_in_deriv(self, values: list[int], n: int) -> Iterable[int]: + while any(values): + yield values[n] + values = self.derive(values) + + def part1(self, inpt: list[list[int]]) -> int: + return sum(sum(self.get_nth_value_in_deriv(line, -1)) for line in inpt) + + def part2(self, inpt: list[list[int]]) -> int: + return sum( + reduce( + lambda acc, x: x - acc, + reversed(list(self.get_nth_value_in_deriv(line, 0))), + ) + for line in inpt + ) + + +def main() -> None: + day09 = Day09(2023, 9, example_code_nr2=0) + day09.run() + + +if __name__ == "__main__": + main()