Python
Solved part 1 in a matter of minutes, spent literal days tinkering with part 2 before resorting to brute force, just to finally get a correct result, which allowed me to fix the more optimised approach. Brute force still turned out surprisingly performant, scaling linearly in time with the rotation distance and sub-linearly in memory.
from itertools import accumulate
from math import copysign
from pathlib import Path
from typing import List
def parse_input(input: str) -> List[int]:
return list(map(lambda s: int(f"{'-' if s[0] == 'L' else ''}{s[1:]}"), input.splitlines()))
def part_one(input: str) -> int:
return len(list(filter(lambda x: x == 0, accumulate(parse_input(input), lambda v, i: (i + v) % 100, initial=50))))
def part_two(input: str) -> int:
v, c = 50, 0
for i in parse_input(input):
c += i // (d := int(copysign(100, i))) # full rotations
count_underflow = v != 0 # was counted in previous iteration
v += (i % d) # remainder
if count_underflow:
c += abs(v // 100) # under-/overflows
if v == 0:
c += 1
v %= 100
return c
if __name__ == "__main__":
input = Path("_2025/_1/input").read_text("utf-8")
print(part_one(input))
print(part_two(input))
Brute force part 2
def part_two(input: str) -> int:
from itertools import chain
return len(list(filter(
lambda x: x == 0,
accumulate(chain(*[[int(copysign(1, i))] * abs(i) for i in parse_input(input)]), lambda v, i: (i + v) % 100, initial = 50)
)))