programming puzzle solutions

cleanup, comment

Changed files
+24 -22
src
2025
+7 -2
README.md
··· 1 1 # Advent of Code 2 - My solutions for Advent of Code in Typescript, Python, and Rust. 2 + My solutions for Advent of Code in Rust, Typescript, and Python. 3 + 4 + For 2025 I'll mostly be focusing on Rust, unless I feel like trying out something new. 5 + 6 + I try to leave comments along the way to explain my reasoning, but if you have any questions feel free to ask me to elaborate on [Bluesky](https://bsky.app/profile/quilling.dev). 7 + 8 + Jump straight to my 2025 Day 1 solution's [Dial struct here!](https://tangled.org/quilling.dev/advent-of-code/blob/main/src/2025/day1/rust/common.rs) Modulo arithmetic handles the dial rotation wraparound logic, and for the second part we just determine the magnitude of the rotation using division before applying it. 3 9 4 10 ![image](https://github.com/Teqed/advent-of-code-2023/assets/5181964/a00fb449-1b3b-4e33-a999-6eef20c773f4) 5 -
+14 -17
src/2025/day1/rust/common.rs
··· 7 7 /// An instruction to rotate the dial. 8 8 pub struct Instruction { 9 9 pub direction: Direction, // L or R. 10 - pub distance: i16, // How many clicks to rotate. 10 + pub distance: u16, // How many clicks to rotate. 11 11 } 12 12 impl Instruction { 13 13 /// Parse an instruction from a line of input (e.g. "L68" or "R48"). ··· 27 27 28 28 /// A safe dial with positions 0-99 that wraps around. 29 29 pub struct Dial { 30 - pub position: i16, // Current position on the dial. 30 + pub position: u16, // Current position on the dial. 31 31 } 32 32 impl Dial { 33 33 /// Create a new dial starting at position 50. ··· 35 35 Self { position: 50 } 36 36 } 37 37 38 - /// Rotate the dial according to an instruction, wrapping around at 0/100. 38 + /// Rotate the dial according to an instruction, wrapping around at 0/99 using modulo arithmetic. 39 + /// 40 + /// The remainder of the modulo operation is effectively, "what remains after subtracting 100 as many times as possible?" 41 + /// This allows us to account for full rotations around the dial and determining what position we should have landed on. 39 42 pub const fn rotate(&mut self, instruction: &Instruction) { 40 43 self.position = match instruction.direction { 41 - Direction::Left => (self.position - instruction.distance).rem_euclid(100), // Wrap around at 0. 42 - Direction::Right => (self.position + instruction.distance).rem_euclid(100), // Wrap around at 100. 44 + Direction::Left => (self.position + 100 - instruction.distance % 100) % 100, // For Left, add 100 before subtracting to avoid negative values. 45 + Direction::Right => (self.position + instruction.distance) % 100, // For Right, simply wrap around at 100. 43 46 }; 44 47 } 45 48 ··· 48 51 self.position == 0 49 52 } 50 53 51 - /// Count how many times the dial passes through 0 during a rotation. 52 - pub const fn count_zero_crossings(&self, instruction: &Instruction) -> i16 { 54 + /// Count how many times the dial passes through 0 during a rotation using division. 55 + pub const fn count_zero_crossings(&self, instruction: &Instruction) -> u16 { 53 56 match instruction.direction { 54 57 Direction::Left => { 55 - let mut first_crossing = self.position; 56 - if first_crossing == 0 { 57 - first_crossing = 100; // If starting at 0, first crossing Left is after full rotation. 58 - } 59 - if instruction.distance < first_crossing { 60 - 0 // Did not reach 0 during this rotation. 61 - } else { 62 - (instruction.distance - first_crossing) / 100 + 1 // Returns number of Left crossings. 63 - } 58 + let first_crossing = if self.position == 0 { 100 } else { self.position }; 59 + if instruction.distance < first_crossing { 0 } // Distance too short to reach first crossing. 60 + else { (instruction.distance - first_crossing) / 100 + 1 } // First crossing + additional full rotations. 64 61 } 65 - Direction::Right => (self.position + instruction.distance) / 100, // Returns number of Right crossings. 62 + Direction::Right => (self.position + instruction.distance) / 100, // Count complete 100-step cycles. 66 63 } 67 64 } 68 65 }
+2 -2
src/2025/day1/rust/part_a.rs
··· 1 1 use super::common::{Dial, Instruction}; 2 2 3 3 /// Count how many times the dial is left pointing at 0 after each rotation. 4 - pub fn part_a(input: &str) -> i16 { 4 + pub fn part_a(input: &str) -> u16 { 5 5 let mut dial = Dial::new(); // Dial starts at position 50. 6 6 let mut count = 0; // Count times dial is left pointing at 0. 7 7 for line in input.lines().filter(|l| !l.is_empty()) { 8 8 let instruction = Instruction::parse(line); 9 9 dial.rotate(&instruction); // Rotate the dial, first. 10 - count += i16::from(dial.is_at_zero()); // Then increment count if at 0. 10 + count += u16::from(dial.is_at_zero()); // Then increment count if at 0. 11 11 } 12 12 count // Return the count of times the dial pointed at 0. 13 13 }
+1 -1
src/2025/day1/rust/part_b.rs
··· 1 1 use super::common::{Dial, Instruction}; 2 2 3 3 /// Count how many times the dial passes through 0 during any rotation. 4 - pub fn part_b(input: &str) -> i16 { 4 + pub fn part_b(input: &str) -> u16 { 5 5 let mut dial = Dial::new(); 6 6 let mut count = 0; 7 7 for line in input.lines().filter(|l| !l.is_empty()) {