+7
-2
README.md
+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

5
-
+14
-17
src/2025/day1/rust/common.rs
+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
+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
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()) {