diff --git a/README.md b/README.md index be56dde..81a0fce 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,4 @@ Development occurs in language-specific directories: |[Day5.hs](hs/src/Day5.hs)|[Day5.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day5.kt)|[day5.py](py/aoc2024/day5.py)|[day5.rs](rs/src/day5.rs)| |[Day6.hs](hs/src/Day6.hs)|[Day6.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day6.kt)|[day6.py](py/aoc2024/day6.py)|[day6.rs](rs/src/day6.rs)| |[Day7.hs](hs/src/Day7.hs)|[Day7.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day7.kt)|[day7.py](py/aoc2024/day7.py)|[day7.rs](rs/src/day7.rs)| -|[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day8.kt)||| +|[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day8.kt)|[day8.py](py/aoc2024/day8.py)|| diff --git a/py/aoc2024/day8.py b/py/aoc2024/day8.py new file mode 100644 index 0000000..e0e720e --- /dev/null +++ b/py/aoc2024/day8.py @@ -0,0 +1,70 @@ +""" +Day 8: Resonant Collinearity +""" + +from collections import defaultdict +from collections.abc import Iterable +from itertools import count + +SAMPLE_INPUT = """ +............ +........0... +.....0...... +.......0.... +....0....... +......A..... +............ +............ +........A... +.........A.. +............ +............ +""" + + +class _Count(Iterable[int]): + def __iter__(self): + return count() + + +def _solve(data: str, multiples: Iterable[int]) -> int: + lines = data.strip("\n").splitlines() + height = len(lines) + width = height and max(map(len, lines)) + antennae = defaultdict(list) + for y, line in enumerate(lines): + for x, char in enumerate(line): + if char != ".": + antennae[char].append((y, x)) + antinodes = set() + for points in antennae.values(): + for y0, x0 in points: + for y1, x1 in points: + if y0 == y1 and x0 == x1: + continue + dy, dx = y1 - y0, x1 - x0 + for i in multiples: + y2, x2 = y1 + i * dy, x1 + i * dx + if y2 not in range(height) or x2 not in range(width): + break + antinodes.add((y2, x2)) + return len(antinodes) + + +def part1(data: str) -> int: + """ + >>> part1(SAMPLE_INPUT) + 14 + """ + return _solve(data, (1,)) + + +def part2(data: str) -> int: + """ + >>> part2(SAMPLE_INPUT) + 34 + """ + return _solve(data, _Count()) + + +parts = (part1, part2) diff --git a/py/pyproject.toml b/py/pyproject.toml index baa714a..896c306 100644 --- a/py/pyproject.toml +++ b/py/pyproject.toml @@ -31,6 +31,7 @@ day4 = "aoc2024.day4:parts" day5 = "aoc2024.day5:parts" day6 = "aoc2024.day6:parts" day7 = "aoc2024.day7:parts" +day8 = "aoc2024.day8:parts" [build-system] requires = ["poetry-core"]