Skip to content

Commit

Permalink
Day 23: Unstable Diffusion
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient committed Dec 23, 2022
1 parent 3324746 commit 6eb0ebb
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ Development occurs in language-specific directories:
|[Day20.hs](hs/src/Day20.hs)|[Day20.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day20.kt)|[day20.py](py/aoc2022/day20.py)|[day20.rs](rs/src/day20.rs)|
|[Day21.hs](hs/src/Day21.hs)|[Day21.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day21.kt)|[day21.py](py/aoc2022/day21.py)|[day21.rs](rs/src/day21.rs)|
|[Day22.hs](hs/src/Day22.hs)|[Day22.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day22.kt)|[day22.py](py/aoc2022/day22.py)|[day22.rs](rs/src/day22.rs)|
|[Day23.hs](hs/src/Day23.hs)|[Day23.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day23.kt)|
|[Day23.hs](hs/src/Day23.hs)|[Day23.kt](kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day23.kt)|[day23.py](py/aoc2022/day23.py)|
107 changes: 107 additions & 0 deletions py/aoc2022/day23.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
"""
Day 23: Unstable Diffusion
"""

from collections import defaultdict
from itertools import cycle, islice

SAMPLE_INPUT = [
"....#..",
"..###.#",
"#...#.#",
".#...##",
"#.###..",
"##.#.##",
".#..#..",
]


def _directions():
return cycle(("NSWE", "SWEN", "WENS", "ENSW"))


def _sides(direction, x, y):
if direction == "N":
return [(x, y - 1) for x in range(x - 1, x + 2)]
if direction == "S":
return [(x, y + 1) for x in range(x - 1, x + 2)]
if direction == "W":
return [(x - 1, y) for y in range(y - 1, y + 2)]
if direction == "E":
return [(x + 1, y) for y in range(y - 1, y + 2)]
raise ValueError()


def _move(direction, x, y):
if direction == "N":
return x, y - 1
if direction == "S":
return x, y + 1
if direction == "W":
return x - 1, y
if direction == "E":
return x + 1, y
raise ValueError()


def _neighbors(x, y):
return [
(x2, y2)
for x2 in range(x - 1, x + 2)
for y2 in range(y - 1, y + 2)
if x2 != x or y2 != y
]


def _parse(lines):
return {
(x, y) for y, line in enumerate(lines) for x, c in enumerate(line) if c == "#"
}


def _step(state, directions):
proposals = defaultdict(list)
for x, y in state:
if not any(neighbor in state for neighbor in _neighbors(x, y)):
continue
for direction in directions:
if not any(neighbor in state for neighbor in _sides(direction, x, y)):
proposals[_move(direction, x, y)].append((x, y))
break
state = set(state)
for new, old in proposals.items():
if len(old) != 1:
continue
state.remove(old[0])
state.add(new)
return state


def part1(lines):
"""
>>> part1(SAMPLE_INPUT)
110
"""
state = _parse(lines)
for directions in islice(_directions(), 10):
state = _step(state, directions)
min_x, max_x = min(x for x, _ in state), max(x for x, _ in state)
min_y, max_y = min(y for _, y in state), max(y for _, y in state)
return (max_y - min_y + 1) * (max_x - min_x + 1) - len(state)


def part2(lines):
"""
>>> part2(SAMPLE_INPUT)
20
"""
state, previous = _parse(lines), None
for i, directions in enumerate(_directions()):
state = _step(state, directions)
if state == previous:
return i + 1
previous = state
raise LookupError()


parts = (part1, part2)
1 change: 1 addition & 0 deletions py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ day19 = "aoc2022.day19:parts"
day20 = "aoc2022.day20:parts"
day21 = "aoc2022.day21:parts"
day22 = "aoc2022.day22:parts"
day23 = "aoc2022.day23:parts"

[tool.black]
target_version = ["py311"]
Expand Down

0 comments on commit 6eb0ebb

Please sign in to comment.