From 88e2d7adff16a869a2fdc256df555e343cac6283 Mon Sep 17 00:00:00 2001 From: Geert Litjens Date: Thu, 14 Dec 2023 21:36:28 +0100 Subject: [PATCH] Day 14 --- src/advent_of_code_2023/days/day14/README.md | 5 ++ .../days/day14/__init__.py | 0 .../days/day14/solution.py | 71 +++++++++++++++++++ tests/test_day14.py | 33 +++++++++ 4 files changed, 109 insertions(+) create mode 100644 src/advent_of_code_2023/days/day14/README.md create mode 100644 src/advent_of_code_2023/days/day14/__init__.py create mode 100644 src/advent_of_code_2023/days/day14/solution.py create mode 100644 tests/test_day14.py diff --git a/src/advent_of_code_2023/days/day14/README.md b/src/advent_of_code_2023/days/day14/README.md new file mode 100644 index 0000000..bfd55da --- /dev/null +++ b/src/advent_of_code_2023/days/day14/README.md @@ -0,0 +1,5 @@ +### Part 1 + + +### Part 2 + diff --git a/src/advent_of_code_2023/days/day14/__init__.py b/src/advent_of_code_2023/days/day14/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/advent_of_code_2023/days/day14/solution.py b/src/advent_of_code_2023/days/day14/solution.py new file mode 100644 index 0000000..5893a12 --- /dev/null +++ b/src/advent_of_code_2023/days/day14/solution.py @@ -0,0 +1,71 @@ +""" +""" + +from advent_of_code_2023.utils import Solution + + +class DaySolution(Solution): + def __init__(self: "DaySolution", day: int = 14, year: int = 2023) -> None: + super().__init__(day, year) + + def _parse_data(self: "DaySolution", input_data: str) -> list[list[str]]: + """ """ + return [[x for x in line] for line in input_data.splitlines()] + + def rotate( + self: "DaySolution", mirrors: list[list[str]], dir: int = 1 + ) -> list[list[str]]: + if dir == 1: + return [list(x) for x in zip(*mirrors[::-1], strict=True)] + else: + return [list(x) for x in zip(*mirrors, strict=True)][::-1] + + def tilt_mirrors(self: "DaySolution", mirrors: list[list[str]]) -> list[list[str]]: + tilted_mirrors = [] + for col in mirrors: + tilted_pieces = [ + "O" * piece.count("O") + "." * (len(piece) - piece.count("O")) + for piece in "".join(col).split("#") + ] + tilted_mirrors.append([x for x in "#".join(tilted_pieces)]) + return tilted_mirrors + + def _solve_part1(self: "DaySolution", parsed_data: list[list[str]]) -> str: + """ """ + mirrors: list[list[str]] = self.rotate(parsed_data) + tilted_mirrors = self.tilt_mirrors(mirrors) + tilted_mirrors = self.rotate(tilted_mirrors) + return str( + sum(["".join(x).count("O") * (i + 1) for i, x in enumerate(tilted_mirrors)]) + ) + + def _solve_part2(self: "DaySolution", parsed_data: list[list[str]]) -> str: + """ """ + cache: dict[str, int] = {} + scores = [] + mirrors = self.rotate(parsed_data, -1) + for cycle in range(1_000_000_000): + for _ in range(4): + mirrors = self.tilt_mirrors(mirrors) + mirrors = self.rotate(mirrors) + + mirrors = self.rotate(mirrors) + str_mirrors = "\n".join(["".join(line) for line in mirrors]) + scores.append( + sum( + [ + "".join(x).count("O") * (len(mirrors) - i) + for i, x in enumerate(mirrors) + ] + ) + ) + mirrors = self.rotate(mirrors, -1) + + if str_mirrors in cache: + prev_cycle = cache[str_mirrors] + cycle_length = cycle - prev_cycle + req_cycle = prev_cycle + (1_000_000_000 - prev_cycle) % cycle_length - 1 + return str(scores[req_cycle]) + else: + cache[str_mirrors] = cycle + return "0" diff --git a/tests/test_day14.py b/tests/test_day14.py new file mode 100644 index 0000000..96663fd --- /dev/null +++ b/tests/test_day14.py @@ -0,0 +1,33 @@ +import pytest + +from advent_of_code_2023.days.day14.solution import DaySolution # type: ignore + + +@pytest.fixture +def day_testdata() -> str: + return """\ +O....#.... +O.OO#....# +.....##... +OO.#O....O +.O.....O#. +O.#..O.#.# +..O..#O..O +.......O.. +#....###.. +#OO..#....\ +""" + + +def test_part1(day_testdata: str) -> None: + sol = DaySolution() + parsed_data = sol._parse_data(day_testdata) + result = sol._solve_part1(parsed_data) + assert result == "136" + + +def test_part2(day_testdata: str) -> None: + sol = DaySolution() + parsed_data = sol._parse_data(day_testdata) + result = sol._solve_part2(parsed_data) + assert result == "64"