From 1e644e14f1d34e35c16378f39654b14940844f9f Mon Sep 17 00:00:00 2001 From: Daniel Lin Date: Thu, 14 Dec 2023 04:55:26 -0500 Subject: [PATCH] Day 14: Parabolic Reflector Dish --- README.md | 2 +- py/aoc2023/day14.py | 76 +++++++++++++++++++++++++++++++++++++++++++++ py/pyproject.toml | 1 + 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 py/aoc2023/day14.py diff --git a/README.md b/README.md index 390c0739..8621f03f 100644 --- a/README.md +++ b/README.md @@ -18,4 +18,4 @@ Development occurs in language-specific directories: |[Day11.hs](hs/src/Day11.hs)|[Day11.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day11.kt)|[day11.py](py/aoc2023/day11.py)|[day11.rs](rs/src/day11.rs)| |[Day12.hs](hs/src/Day12.hs)|[Day12.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day12.kt)|[day12.py](py/aoc2023/day12.py)|[day12.rs](rs/src/day12.rs)| |[Day13.hs](hs/src/Day13.hs)|[Day13.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day13.kt)|[day13.py](py/aoc2023/day13.py)|[day13.rs](rs/src/day13.rs)| -|[Day14.hs](hs/src/Day14.hs)|[Day14.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day14.kt)||| +|[Day14.hs](hs/src/Day14.hs)|[Day14.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day14.kt)|[day14.py](py/aoc2023/day14.py)|| diff --git a/py/aoc2023/day14.py b/py/aoc2023/day14.py new file mode 100644 index 00000000..a0189637 --- /dev/null +++ b/py/aoc2023/day14.py @@ -0,0 +1,76 @@ +""" +Day 14: Parabolic Reflector Dish +""" + +from itertools import islice + +SAMPLE_INPUT = """ +O....#.... +O.OO#....# +.....##... +OO.#O....O +.O.....O#. +O.#..O.#.# +..O..#O..O +.......O.. +#....###.. +#OO..#.... +""" + + +def _tilt(data): + data = list(map(list, data)) + for x in range(max(map(len, data))): + y0 = 0 + while y0 < len(data): + n, y1 = 0, y0 + while y1 < len(data): + c = data[y1][x] + if c == "O": + n += 1 + elif c == "#": + break + y1 += 1 + for y in range(y0, y1): + data[y][x] = "O" if y < y0 + n else "." + y0 = y1 + 1 + return data + + +def _spin(data): + for _ in range(3): + data = list(zip(*_tilt(data)[::-1])) + return tuple(map("".join, zip(*_tilt(data)[::-1]))) + + +def _load(data): + return sum((len(line) - i) * line.count("O") for i, line in enumerate(data)) + + +def part1(data): + """ + >>> part1(SAMPLE_INPUT) + 136 + """ + return _load(_tilt(filter(None, data.splitlines()))) + + +def part2(data): + """ + >>> part2(SAMPLE_INPUT) + 64 + """ + n = 1000000000 + data = tuple(filter(None, data.splitlines())) + cache = {data: 0} + for i in range(1, n + 1): + data = _spin(data) + if data in cache: + j = cache[data] + data = next(islice(cache.keys(), j + (n - i) % (i - j), None)) + break + cache[data] = i + return _load(data) + + +parts = (part1, part2) diff --git a/py/pyproject.toml b/py/pyproject.toml index f5490fe4..2fe8bf3d 100644 --- a/py/pyproject.toml +++ b/py/pyproject.toml @@ -35,6 +35,7 @@ day10 = "aoc2023.day10:parts" day11 = "aoc2023.day11:parts" day12 = "aoc2023.day12:parts" day13 = "aoc2023.day13:parts" +day14 = "aoc2023.day14:parts" [tool.black] target_version = ["py312"]