//// Authored-by: Claude Opus 4.5 via Crush import gleam/int import gleam/list import gleam/result import gleam/string pub type Rotation { Left(Int) Right(Int) } fn parse_rotation(s: String) -> Result(Rotation, Nil) { let s = string.trim(s) case string.first(s) { Ok("L") -> s |> string.drop_start(1) |> int.parse |> result.map(Left) Ok("R") -> s |> string.drop_start(1) |> int.parse |> result.map(Right) _ -> Error(Nil) } } fn apply_rotation(position: Int, rotation: Rotation) -> Int { let new_pos = case rotation { Left(n) -> position - n Right(n) -> position + n } // Wrap around 0-99 (100 positions) { { new_pos % 100 } + 100 } % 100 } pub fn part1(input: List(String)) -> Int { let rotations = list.filter_map(input, parse_rotation) let #(zero_count, _final_pos) = list.fold(rotations, #(0, 50), fn(acc, rotation) { let #(count, pos) = acc let new_pos = apply_rotation(pos, rotation) let new_count = case new_pos { 0 -> count + 1 _ -> count } #(new_count, new_pos) }) zero_count } fn count_zeros_crossed(position: Int, rotation: Rotation) -> Int { let #(steps, going_right) = case rotation { Left(n) -> #(n, False) Right(n) -> #(n, True) } case going_right { True -> { // Right: hit 0 when (position + k) % 100 == 0 let first_hit = { 100 - position } % 100 case first_hit { 0 -> steps / 100 f if f <= steps -> { steps - f } / 100 + 1 _ -> 0 } } False -> { // Left: hit 0 when (position - k) % 100 == 0, i.e., k == position case position { 0 -> steps / 100 p if p <= steps -> { steps - p } / 100 + 1 _ -> 0 } } } } pub fn part2(input: List(String)) -> Int { let rotations = list.filter_map(input, parse_rotation) let #(zero_count, _final_pos) = list.fold(rotations, #(0, 50), fn(acc, rotation) { let #(count, pos) = acc let zeros = count_zeros_crossed(pos, rotation) let new_pos = apply_rotation(pos, rotation) #(count + zeros, new_pos) }) zero_count }