Skip to content

Commit

Permalink
Day 6: Guard Gallivant
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient committed Dec 6, 2024
1 parent 85f3460 commit 96b0ac6
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Development occurs in language-specific directories:
|[Day3.hs](hs/src/Day3.hs)|[Day3.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day3.kt)|[day3.py](py/aoc2024/day3.py)|[day3.rs](rs/src/day3.rs)|
|[Day4.hs](hs/src/Day4.hs)|[Day4.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day4.kt)|[day4.py](py/aoc2024/day4.py)|[day4.rs](rs/src/day4.rs)|
|[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.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)||
108 changes: 108 additions & 0 deletions py/aoc2024/day6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"""
Day 6: Guard Gallivant
"""

from functools import partial
from multiprocessing import Pool
from typing import Generator, Iterable, Set, Tuple

SAMPLE_INPUT = """
....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...
"""


def _parse(data: str) -> Tuple[Tuple[int, int], Tuple[int, int], Set[Tuple[int, int]]]:
obstructions = []
for y, line in enumerate(filter(None, data.splitlines())):
for x, char in enumerate(line):
match char:
case "^":
initial_y, initial_x = y, x
case "#":
obstructions.append((y, x))
return (initial_y, initial_x), (y + 1, len(line)), frozenset(obstructions)


def _visit(
initial_pos: Tuple[int, int],
max_bounds: Tuple[int, int],
obstructions: Iterable[Tuple[int, int]],
) -> Generator[Tuple[int, int], None, Set[Tuple[int, int]]]:
y, x = initial_pos
dy, dx = -1, 0
max_y, max_x = max_bounds
visited = set()
while True:
yield (y, x), (dy, dx)
visited.add((y, x))
next_y, next_x = y + dy, x + dx
if next_y not in range(max_y) or next_x not in range(max_x):
break
if (next_y, next_x) in obstructions:
dy, dx = dx, -dy
else:
y, x = next_y, next_x
return visited


def _part1(
initial_pos: Tuple[int, int],
max_bounds: Tuple[int, int],
obstructions: Iterable[Tuple[int, int]],
) -> Set[Tuple[int, int]]:
visitor = _visit(initial_pos, max_bounds, obstructions)
while True:
try:
next(visitor)
except StopIteration as error:
return error.value


def part1(data: str) -> int:
"""
>>> part1(SAMPLE_INPUT)
41
"""
initial_pos, max_bounds, obstructions = _parse(data)
return len(_part1(initial_pos, max_bounds, obstructions))


def _part2(
initial_pos: Tuple[int, int],
max_bounds: Tuple[int, int],
obstructions: Iterable[Tuple[int, int]],
) -> bool:
visited = set()
for key in _visit(initial_pos, max_bounds, obstructions):
if key in visited:
return True
visited.add(key)
return False


def part2(data: str, concurrency: int = None) -> int:
"""
>>> part2(SAMPLE_INPUT)
6
"""
initial_pos, max_bounds, obstructions = _parse(data)
candidates = _part1(initial_pos, max_bounds, obstructions) - {initial_pos}
with Pool(concurrency) as pool:
return sum(
pool.imap_unordered(
partial(_part2, initial_pos, max_bounds),
(obstructions | {candidate} for candidate in candidates),
)
)


parts = (part1, part2)
40 changes: 20 additions & 20 deletions py/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ python = "^3.13"
natsort = "^8.4.0"

[tool.poetry.group.dev.dependencies]
ruff = "^0.8.1"
ruff = "^0.8.2"
pytest = "^8.3.4"
pytest-benchmark = { version = "^5.1.0", extras = ["histogram"] }

Expand All @@ -29,6 +29,7 @@ day2 = "aoc2024.day2:parts"
day3 = "aoc2024.day3:parts"
day4 = "aoc2024.day4:parts"
day5 = "aoc2024.day5:parts"
day6 = "aoc2024.day6:parts"

[build-system]
requires = ["poetry-core"]
Expand Down

0 comments on commit 96b0ac6

Please sign in to comment.