1import gleam/int
2import gleam/list
3import gleam/result
4import gleam/string
5
6const starting_position = 50
7
8pub type Movement {
9 Left(Int)
10 Right(Int)
11}
12
13pub fn part1(input: List(String)) -> Int {
14 let movements = input |> list.filter_map(parse_movement)
15 let #(zero_count, _final_pos) =
16 list.fold(movements, #(0, starting_position), fn(acc, movement) {
17 let #(count, pos) = acc
18 let new_pos = apply_movement(pos, movement)
19 let new_count = case new_pos {
20 0 -> count + 1
21 _ -> count
22 }
23 #(new_count, new_pos)
24 })
25 zero_count
26}
27
28pub fn part2(input: List(String)) -> Int {
29 let movements = input |> list.filter_map(parse_movement)
30 let #(zero_count, _final_pos) =
31 list.fold(movements, #(0, starting_position), fn(acc, movement) {
32 let #(count, pos) = acc
33 let new_pos = apply_movement(pos, movement)
34 let zeroes = zeroes_hit(pos, movement)
35 #(count + zeroes, new_pos)
36 })
37 zero_count
38}
39
40pub fn parse_movement(input: String) -> Result(Movement, Nil) {
41 case string.first(input) {
42 Ok("L") ->
43 input
44 |> string.drop_start(1)
45 |> int.parse
46 |> result.map(Left)
47 Ok("R") ->
48 input
49 |> string.drop_start(1)
50 |> int.parse
51 |> result.map(Right)
52 _ -> Error(Nil)
53 }
54}
55
56fn apply_movement(position: Int, movement: Movement) -> Int {
57 let new_pos = case movement {
58 Left(n) -> position - n
59 Right(n) -> position + n
60 }
61 // Wrap around 0-99 (100 positions)
62 { { new_pos % 100 } + 100 } % 100
63}
64
65fn zeroes_hit(position: Int, movement: Movement) -> Int {
66 let #(steps, going_right) = case movement {
67 Left(n) -> #(n, False)
68 Right(n) -> #(n, True)
69 }
70
71 case going_right {
72 True -> {
73 // Right: hit 0 when (position + k) % 100 == 0
74 let first_hit = { 100 - position } % 100
75 case first_hit {
76 0 -> steps / 100
77 f if f <= steps -> { steps - f } / 100 + 1
78 _ -> 0
79 }
80 }
81 False -> {
82 // Left: hit 0 when (position - k) % 100 == 0, i.e., k == position
83 case position {
84 0 -> steps / 100
85 p if p <= steps -> { steps - p } / 100 + 1
86 _ -> 0
87 }
88 }
89 }
90}