Musings from the mountains himwant.org

Advent of Code Day 1

+317 -26
+174 -25
src/content/aoc/2025/01.md
··· 1 1 --- 2 2 title: "Secret Entrance" 3 - published: 2025-12-15 3 + published: 2025-12-16 4 4 draft: false 5 5 --- 6 6 ··· 10 10 11 11 We are given line seperated operations that happen on a 100 pin circular dial. The dial starts at 50 and we are to output, how many times the dial stops at 0! 12 12 13 - An example- 13 + We first, as expected, just take in the input and initialise variables to store current dial position and total number of times the dial has stopped at 0. 14 + 15 + ```rust title="setup" 16 + use std::fs::read_to_string; 17 + fn main() { 18 + let contents = read_to_string("./input.txt").unwrap(); 19 + let mut curr: i32 = 50; 20 + let mut tot = 0; 21 + 22 + <<logic_loop>> 23 + 24 + println!("Password: {tot}"); 25 + } 26 + ``` 27 + 28 + We go through each line of input, and parse it. Our input is in the form -"L50" where the first character is the direction in which the dial is to be rotated and the rest is the amplitude. 29 + 30 + ```rust title="logic_loop" 31 + for line in contents.lines() { 32 + let words: Vec<char> = line.chars().collect(); 33 + let dir = words[0]; 34 + let amp: String = words[1..].iter().collect(); 35 + let amp: i32 = amp.parse().unwrap(); 36 + 37 + <<rotate_dial>> 38 + } 39 + ``` 40 + 41 + Now that we have both the dir and the amp, we can modify the dial position. 42 + 43 + ```rust title="rotate_dial" 44 + if dir == 'L' { 45 + curr -= amp; 46 + } else { 47 + curr += amp; 48 + } 49 + 50 + <<loopback>> 51 + ``` 52 + 53 + The value of curr could have gone above 99 or below 0, which we need to rectify. 54 + 55 + ```rust title="loopback" 56 + if curr < 0 { 57 + curr = 100 + curr; 58 + } 59 + 60 + curr = curr % 100; 61 + 62 + <<count_zeros>> 63 + ``` 64 + 65 + Now that we have the current position of the dial, we only need to check if it currently points at 0, and increment `tot`, if it does. 66 + 67 + ```rust title="count_zeros" 68 + if curr == 0 { 69 + tot += 1; 70 + } 71 + ``` 72 + 73 + We have the final program- 74 + 75 + ```rust title="Full Program" 76 + use std::fs::read_to_string; 77 + fn main() { 78 + let contents = read_to_string("./input.txt").unwrap(); 79 + let mut curr: i32 = 50; 80 + let mut tot = 0; 81 + 82 + for line in contents.lines() { 83 + let words: Vec<char> = line.chars().collect(); 84 + let dir = words[0]; 85 + let amp: String = words[1..].iter().collect(); 86 + let amp: i32 = amp.parse().unwrap(); 87 + 88 + if dir == 'L' { 89 + curr -= amp; 90 + } else { 91 + curr += amp; 92 + } 93 + 94 + if curr < 0 { 95 + curr = 100 + curr; 96 + } 97 + 98 + curr = curr % 100; 99 + 100 + if curr == 0 { 101 + tot += 1; 102 + } 103 + } 104 + 105 + println!("Password: {tot}"); 106 + } 107 + ``` 108 + 109 + 110 + # Part 2 111 + 112 + Another complication has been added to our little problem! Now we not only need to say how many times the dial stopped at 0, but also how many times it crossed it! 113 + 114 + We add two new variables that are going to help us! `prev` and `cross`. We are going to keep `tot` and its related logic and add onto it! 115 + 116 + ```rust 117 + // In setup 118 + let mut prev: i32 = 50; 119 + let mut cross = 0; 120 + ``` 121 + 122 + If the amplitude is >100, that means atleast one full rotation, therefore, atleast oe crossing of 0! We can figure out the number of crossing here using division. We also bring the value of amp to the range [0, 99]. 123 + 124 + ```rust 125 + cross += amp / 100; 126 + let amp = amp % 100; 127 + ``` 128 + 129 + And easy way to detect a crossing is to check if the difference in `curr` and `prev` is opposite to what we expected. For example, let's say dial position is at `5` and we get input `L10`, as the `dir` is `L`, the dial position should decrease, that is, `curr` < `prev`, but as the `amp` was 10, the new dial position becomes `95`. Now, `curr` (95) > `prev` (5). Detecting for this, and similarly `curr` < `prev` for `R`, we can get if there was a crossing on this move! One thing we need to keep in mind is to ignore those where either `curr` or `prev` were 0, as they would have been already counted by `tot`! 130 + 131 + :::duck 132 + Also, do remember to set `prev = curr` at the end, you don't want to know how much time I spent debugging this! 133 + ::: 134 + 135 + ```rust 136 + if ((dir == 'L' && prev < curr) || (dir == 'R' && prev > curr)) && curr != 0 && prev != 0 { 137 + cross += 1; 138 + } 139 + 140 + prev = curr; 141 + ``` 142 + 143 + Our final program- 144 + 145 + ```rust title="main.rs" 146 + use std::fs::read_to_string; 147 + 148 + fn main() { 149 + let contents = read_to_string("./input.txt").unwrap(); 150 + 151 + let mut curr: i32 = 50; 152 + let mut prev: i32 = 50; 153 + let mut tot = 0; 154 + let mut cross = 0; 155 + 156 + for line in contents.lines() { 157 + let words: Vec<char> = line.chars().collect(); 158 + let dir = words[0]; 159 + let amp: String = words[1..].iter().collect(); 160 + let amp: i32 = amp.parse().unwrap(); 161 + 162 + cross += amp / 100; 163 + let amp = amp % 100; 164 + 165 + if dir == 'L' { 166 + curr -= amp; 167 + } else { 168 + curr += amp; 169 + } 170 + 171 + if curr < 0 { 172 + curr = 100 + curr; 173 + } 174 + curr = curr % 100; 14 175 15 - > L68 16 - > L30 17 - > R48 18 - > L5 19 - > R60 20 - > L55 21 - > L1 22 - > L99 23 - > R14 24 - > L82 176 + if curr == 0 { 177 + tot += 1; 178 + } 179 + if ((dir == 'L' && prev < curr) || (dir == 'R' && prev > curr)) && curr != 0 && prev != 0 { 180 + cross += 1; 181 + } 25 182 26 - - Dial @ 50 27 - - L68 -> 82 28 - - L30 -> 52 29 - - R48 -> **0**! 30 - - L5 -> 95 31 - - R60 -> 55 32 - - L55 -> **0**! 33 - - L1 -> 99 34 - - L99 -> **0**! 35 - - R14 -> 14 36 - - L82 -> 32 37 - 38 - So, in total `3` times! `3` is our answer! 183 + prev = curr; 184 + } 185 + println!("Password: {}", cross + tot); 186 + } 187 + ``` 39 188
+143 -1
src/content/aoc/2025/01.org
··· 1 1 #+title: Secret Entrance 2 2 #+OPTIONS: toc:nil 3 + #+PROPERTY: header-args:rust :noweb no-export 3 4 4 5 * Part 1 5 6 We are given line seperated operations that happen on a 100 pin circular dial. The dial starts at 50 and we are to output, how many times the dial stops at 0! 6 7 8 + 9 + We first, as expected, just take in the input and initialise variables to store current dial position and total number of times the dial has stopped at 0. 10 + #+name: setup 11 + #+begin_src rust :title "setup" 12 + use std::fs::read_to_string; 13 + fn main() { 14 + let contents = read_to_string("./input.txt").unwrap(); 15 + let mut curr: i32 = 50; 16 + let mut tot = 0; 17 + 18 + <<logic_loop>> 19 + 20 + println!("Password: {tot}"); 21 + } 22 + #+end_src 23 + 24 + We go through each line of input, and parse it. Our input is in the form -"L50" where the first character is the direction in which the dial is to be rotated and the rest is the amplitude. 25 + 26 + #+name: logic_loop 27 + #+begin_src rust :title "logic_loop" 28 + for line in contents.lines() { 29 + let words: Vec<char> = line.chars().collect(); 30 + let dir = words[0]; 31 + let amp: String = words[1..].iter().collect(); 32 + let amp: i32 = amp.parse().unwrap(); 33 + 34 + <<rotate_dial>> 35 + } 36 + #+end_src 37 + 38 + Now that we have both the dir and the amp, we can modify the dial position. 39 + #+name: rotate_dial 40 + #+begin_src rust :title "rotate_dial" 41 + if dir == 'L' { 42 + curr -= amp; 43 + } else { 44 + curr += amp; 45 + } 46 + 47 + <<loopback>> 48 + #+end_src 49 + 50 + The value of curr could have gone above 99 or below 0, which we need to rectify. 51 + #+name: loopback 52 + #+begin_src rust :title "loopback" 53 + if curr < 0 { 54 + curr = 100 + curr; 55 + } 56 + 57 + curr = curr % 100; 58 + 59 + <<count_zeros>> 60 + #+end_src 61 + 62 + Now that we have the current position of the dial, we only need to check if it currently points at 0, and increment =tot=, if it does. 63 + #+name: count_zeros 64 + #+begin_src rust :title "count_zeros" 65 + if curr == 0 { 66 + tot += 1; 67 + } 68 + #+end_src 69 + 70 + We have the final program- 71 + 72 + #+begin_src rust :noweb yes :title "Full Program" 73 + <<setup>> 74 + #+end_src 75 + 76 + * Part 2 77 + 78 + Another complication has been added to our little problem! Now we not only need to say how many times the dial stopped at 0, but also how many times it crossed it! 79 + 80 + We add two new variables that are going to help us! =prev= and =cross=. We are going to keep =tot= and its related logic and add onto it! 81 + 7 82 #+begin_src rust 83 + // In setup 84 + let mut prev: i32 = 50; 85 + let mut cross = 0; 8 86 #+end_src 9 87 10 - #+RESULTS: 88 + If the amplitude is >100, that means atleast one full rotation, therefore, atleast oe crossing of 0! We can figure out the number of crossing here using division. We also bring the value of amp to the range [0, 99]. 89 + #+begin_src rust 90 + cross += amp / 100; 91 + let amp = amp % 100; 92 + #+end_src 93 + 94 + And easy way to detect a crossing is to check if the difference in =curr= and =prev= is opposite to what we expected. For example, let's say dial position is at =5= and we get input =L10=, as the =dir= is =L=, the dial position should decrease, that is, =curr= < =prev=, but as the =amp= was 10, the new dial position becomes =95=. Now, =curr= (95) > =prev= (5). Detecting for this, and similarly =curr= < =prev= for =R=, we can get if there was a crossing on this move! One thing we need to keep in mind is to ignore those where either =curr= or =prev= were 0, as they would have been already counted by =tot=! 95 + 96 + :::duck 97 + Also, do remember to set =prev = curr= at the end, you don't want to know how much time I spent debugging this! 98 + ::: 99 + 100 + #+begin_src rust 101 + if ((dir == 'L' && prev < curr) || (dir == 'R' && prev > curr)) && curr != 0 && prev != 0 { 102 + cross += 1; 103 + } 104 + 105 + prev = curr; 106 + #+end_src 107 + 108 + 109 + Our final program- 110 + #+begin_src rust :title "main.rs" 111 + use std::fs::read_to_string; 112 + 113 + fn main() { 114 + let contents = read_to_string("./input.txt").unwrap(); 115 + 116 + let mut curr: i32 = 50; 117 + let mut prev: i32 = 50; 118 + let mut tot = 0; 119 + let mut cross = 0; 120 + 121 + for line in contents.lines() { 122 + let words: Vec<char> = line.chars().collect(); 123 + let dir = words[0]; 124 + let amp: String = words[1..].iter().collect(); 125 + let amp: i32 = amp.parse().unwrap(); 126 + 127 + cross += amp / 100; 128 + let amp = amp % 100; 129 + 130 + if dir == 'L' { 131 + curr -= amp; 132 + } else { 133 + curr += amp; 134 + } 135 + 136 + if curr < 0 { 137 + curr = 100 + curr; 138 + } 139 + curr = curr % 100; 140 + 141 + if curr == 0 { 142 + tot += 1; 143 + } 144 + if ((dir == 'L' && prev < curr) || (dir == 'R' && prev > curr)) && curr != 0 && prev != 0 { 145 + cross += 1; 146 + } 147 + 148 + prev = curr; 149 + } 150 + println!("Password: {}", cross + tot); 151 + } 152 + #+end_src