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.
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)
)))