Musings from the mountains himwant.org

AoC Day 2

+308
+188
src/content/aoc/2025/02.md
··· 1 + --- 2 + title: "Gift Shop" 3 + published: 2025-12-18 4 + draft: false 5 + --- 6 + 7 + We are given comma-separated ranges of numbers that we have to check, we sum all the numbers which are n repeating blocks, for example, 123123 has n = 2, and block = 123, similarly, 111, has n = 3, and block = 1! Part 1 has n = 2, and Part 2 can have any value as n! So we can just directly solve Part 2 (although I did solve Part 1 as a standalone problem first). Let's get started&#x2026; 8 + 9 + 10 + # Boilerplate 11 + 12 + ```rust 13 + use std::fs; 14 + 15 + fn main() { 16 + let input = fs::read_to_string("./input.txt").unwrap(); 17 + let ranges = input.split(","); 18 + let mut sum = 0; 19 + for range in ranges { 20 + let mut nums = range.split("-"); 21 + 22 + let start: u64 = nums.next().unwrap().trim().parse().unwrap(); 23 + let end: u64 = nums.next().unwrap().trim().parse().unwrap(); 24 + 25 + for i in start..=end { 26 + let i_str = i.to_string(); 27 + 28 + if check(i_str) { 29 + sum += i; 30 + } 31 + } 32 + } 33 + println!("Sum: {sum}"); 34 + } 35 + ``` 36 + 37 + We parse the input, and send the number (as a string) to `check` function for the actual logic. 38 + 39 + 40 + # check 41 + 42 + ```rust title="check" 43 + fn check(i_str: String) -> bool { 44 + for check_len in 1..i_str.len() { 45 + if check_n(&i_str, check_len) { 46 + return true; 47 + } 48 + } 49 + return false; 50 + } 51 + ``` 52 + 53 + We start with n=1 and go up to the length of the string checking if it has 'n' repeating blocks! 54 + 55 + 56 + # check<sub>n</sub> 57 + 58 + check<sub>n</sub> actually performs the logic- 59 + 60 + 1. It is obviously not going to be 'n' repeating blocks if the length of the string is not even divisible by n! 61 + 62 + ```rust 63 + if i_str.len() % check_len != 0 { 64 + return false; 65 + } 66 + ``` 67 + 68 + 2. Setup block content 69 + 70 + ```rust 71 + let nums = i_str.char_indices(); 72 + 73 + let mut curr = String::new(); 74 + let comp = &i_str[0..check_len]; 75 + ``` 76 + 77 + 3. Now we append each character to `curr`, and on every 'n'th character, we compare `curr` and `comp`, if it is different, we return false, otherwise we clear `curr` and continue. 78 + 79 + ```rust 80 + for (id, c) in nums { 81 + if id % check_len == 0 && id != 0 { 82 + if comp != curr { 83 + return false; 84 + } 85 + curr = String::new(); 86 + } 87 + curr.push(c); 88 + } 89 + ``` 90 + 91 + 4. We also need to check the last block 92 + 93 + ```rust 94 + if comp != curr { 95 + return false; 96 + } 97 + ``` 98 + 99 + 5. We return true, if all blocks are same 100 + 101 + ```rust 102 + true 103 + ``` 104 + 105 + Our Final check<sub>n</sub> function- 106 + 107 + ```rust title="check_n" 108 + fn check_n(i_str: &str, check_len: usize) -> bool { 109 + if i_str.len() % check_len != 0 { 110 + return false; 111 + } 112 + let nums = i_str.char_indices(); 113 + 114 + let mut curr = String::new(); 115 + let comp = &i_str[0..check_len]; 116 + for (id, c) in nums { 117 + if id % check_len == 0 && id != 0 { 118 + if comp != curr { 119 + return false; 120 + } 121 + curr = String::new(); 122 + } 123 + curr.push(c); 124 + } 125 + if comp != curr { 126 + return false; 127 + } 128 + true 129 + } 130 + ``` 131 + 132 + Which gives us our final program- 133 + 134 + ```rust title="main.rs" 135 + use std::fs; 136 + 137 + fn main() { 138 + let input = fs::read_to_string("./input.txt").unwrap(); 139 + let ranges = input.split(","); 140 + let mut sum = 0; 141 + for range in ranges { 142 + let mut nums = range.split("-"); 143 + 144 + let start: u64 = nums.next().unwrap().trim().parse().unwrap(); 145 + let end: u64 = nums.next().unwrap().trim().parse().unwrap(); 146 + 147 + for i in start..=end { 148 + let i_str = i.to_string(); 149 + 150 + if check(i_str) { 151 + sum += i; 152 + } 153 + } 154 + } 155 + println!("Sum: {sum}"); 156 + } 157 + fn check(i_str: String) -> bool { 158 + for check_len in 1..i_str.len() { 159 + if check_n(&i_str, check_len) { 160 + return true; 161 + } 162 + } 163 + return false; 164 + } 165 + fn check_n(i_str: &str, check_len: usize) -> bool { 166 + if i_str.len() % check_len != 0 { 167 + return false; 168 + } 169 + let nums = i_str.char_indices(); 170 + 171 + let mut curr = String::new(); 172 + let comp = &i_str[0..check_len]; 173 + for (id, c) in nums { 174 + if id % check_len == 0 && id != 0 { 175 + if comp != curr { 176 + return false; 177 + } 178 + curr = String::new(); 179 + } 180 + curr.push(c); 181 + } 182 + if comp != curr { 183 + return false; 184 + } 185 + true 186 + } 187 + ``` 188 +
+120
src/content/aoc/2025/02.org
··· 1 + #+title: Gift Shop 2 + #+OPTIONS: toc:nil 3 + #+PROPERTY: header-args:rust :noweb no-export 4 + 5 + We are given comma-separated ranges of numbers that we have to check, we sum all the numbers which are n repeating blocks, for example, 123123 has n = 2, and block = 123, similarly, 111, has n = 3, and block = 1! Part 1 has n = 2, and Part 2 can have any value as n! So we can just directly solve Part 2 (although I did solve Part 1 as a standalone problem first). Let's get started... 6 + 7 + 8 + ** Boilerplate 9 + #+name: boiler 10 + #+begin_src rust 11 + use std::fs; 12 + 13 + fn main() { 14 + let input = fs::read_to_string("./input.txt").unwrap(); 15 + let ranges = input.split(","); 16 + let mut sum = 0; 17 + for range in ranges { 18 + let mut nums = range.split("-"); 19 + 20 + let start: u64 = nums.next().unwrap().trim().parse().unwrap(); 21 + let end: u64 = nums.next().unwrap().trim().parse().unwrap(); 22 + 23 + for i in start..=end { 24 + let i_str = i.to_string(); 25 + 26 + if check(i_str) { 27 + sum += i; 28 + } 29 + } 30 + } 31 + println!("Sum: {sum}"); 32 + } 33 + #+end_src 34 + 35 + We parse the input, and send the number (as a string) to =check= function for the actual logic. 36 + 37 + ** check 38 + #+name: check 39 + #+begin_src rust :title "check" 40 + fn check(i_str: String) -> bool { 41 + for check_len in 1..i_str.len() { 42 + if check_n(&i_str, check_len) { 43 + return true; 44 + } 45 + } 46 + return false; 47 + } 48 + #+end_src 49 + We start with n=1 and go up to the length of the string checking if it has 'n' repeating blocks! 50 + 51 + ** check_n 52 + check_n actually performs the logic- 53 + 54 + 1. It is obviously not going to be 'n' repeating blocks if the length of the string is not even divisible by n! 55 + #+name: cn_1 56 + #+begin_src rust 57 + if i_str.len() % check_len != 0 { 58 + return false; 59 + } 60 + #+end_src 61 + 62 + 2. Setup block content 63 + #+name: cn_2 64 + #+begin_src rust 65 + let nums = i_str.char_indices(); 66 + 67 + let mut curr = String::new(); 68 + let comp = &i_str[0..check_len]; 69 + #+end_src 70 + 71 + 3. Now we append each character to =curr=, and on every 'n'th character, we compare =curr= and =comp=, if it is different, we return false, otherwise we clear =curr= and continue. 72 + #+name: cn_3 73 + #+begin_src rust 74 + for (id, c) in nums { 75 + if id % check_len == 0 && id != 0 { 76 + if comp != curr { 77 + return false; 78 + } 79 + curr = String::new(); 80 + } 81 + curr.push(c); 82 + } 83 + #+end_src 84 + 85 + 4. We also need to check the last block 86 + #+name: cn_4 87 + #+begin_src rust 88 + if comp != curr { 89 + return false; 90 + } 91 + #+end_src 92 + 93 + 5. We return true, if all blocks are same 94 + #+name: cn_5 95 + #+begin_src rust 96 + true 97 + #+end_src 98 + 99 + Our Final check_n function- 100 + 101 + #+name: check_n 102 + #+begin_src rust :title "check_n" :noweb yes 103 + fn check_n(i_str: &str, check_len: usize) -> bool { 104 + <<cn_1>> 105 + <<cn_2>> 106 + <<cn_3>> 107 + <<cn_4>> 108 + <<cn_5>> 109 + } 110 + #+end_src 111 + 112 + 113 + 114 + 115 + Which gives us our final program- 116 + #+begin_src rust :title "main.rs" :noweb yes 117 + <<boiler>> 118 + <<check>> 119 + <<check_n>> 120 + #+end_src