Skip to content

Commit

Permalink
Day 8: Haunted Wasteland
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient committed Dec 8, 2023
1 parent 94cf2a3 commit daaed35
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ Development occurs in language-specific directories:
|[Day5.hs](hs/src/Day5.hs)|[Day5.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day5.kt)|[day5.py](py/aoc2023/day5.py)|[day5.rs](rs/src/day5.rs)|
|[Day6.hs](hs/src/Day6.hs)|[Day6.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day6.kt)|[day6.py](py/aoc2023/day6.py)|[day6.rs](rs/src/day6.rs)|
|[Day7.hs](hs/src/Day7.hs)|[Day7.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day7.kt)|[day7.py](py/aoc2023/day7.py)|[day7.rs](rs/src/day7.rs)|
|[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day8.kt)|||
|[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2023-lib/src/commonMain/kotlin/com/github/ephemient/aoc2023/Day8.kt)|[day8.py](py/aoc2023/day8.py)||
100 changes: 100 additions & 0 deletions py/aoc2023/day8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"""
Day 8: Haunted Wasteland
"""

import re
from functools import reduce
from itertools import accumulate, repeat
from math import lcm

SAMPLE_INPUT_1, SAMPLE_INPUT_2, SAMPLE_INPUT_3 = (
"""RL
AAA = (BBB, CCC)
BBB = (DDD, EEE)
CCC = (ZZZ, GGG)
DDD = (DDD, DDD)
EEE = (EEE, EEE)
GGG = (GGG, GGG)
ZZZ = (ZZZ, ZZZ)
""",
"""LLR
AAA = (BBB, BBB)
BBB = (AAA, ZZZ)
ZZZ = (ZZZ, ZZZ)
""",
"""LR
11A = (11B, XXX)
11B = (XXX, 11Z)
11Z = (11B, XXX)
22A = (22B, XXX)
22B = (22C, 22C)
22C = (22Z, 22Z)
22Z = (22B, 22B)
XXX = (XXX, XXX)
""",
)

INSTRUCTIONS = re.compile(r"[LR]+")
NODE = re.compile(r"(\w+) = \((\w+), (\w+)\)")


def _parse(data):
instructions = INSTRUCTIONS.match(data).group()
table = {node: (left, right) for node, left, right in NODE.findall(data)}

def step(node, instruction):
match instruction:
case "L":
return table[node][0]
case "R":
return table[node][1]

return (
lambda start: reduce(step, instructions, start),
len(instructions),
table.keys(),
)


def part1(data):
"""
>>> part1(SAMPLE_INPUT_1)
2
>>> part1(SAMPLE_INPUT_2)
6
"""
step, n, _ = _parse(data)
return n * next(
i
for i, node in enumerate(
accumulate(repeat(()), lambda node, _: step(node), initial="AAA")
)
if node == "ZZZ"
)


def part2(data):
"""
>>> part2(SAMPLE_INPUT_3)
6
"""
step, n, nodes = _parse(data)

def find_cycle(start):
i, end = next(
(i, node)
for i, node in enumerate(
accumulate(repeat(()), lambda node, _: step(node), initial=start)
)
if node.endswith("Z")
)
assert step(start) == step(end)
return i

return n * reduce(lcm, (find_cycle(node) for node in nodes if node.endswith("A")))


parts = (part1, part2)
1 change: 1 addition & 0 deletions py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ day4 = "aoc2023.day4:parts"
day5 = "aoc2023.day5:parts"
day6 = "aoc2023.day6:parts"
day7 = "aoc2023.day7:parts"
day8 = "aoc2023.day8:parts"

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

0 comments on commit daaed35

Please sign in to comment.