This commit is contained in:
2025-12-01 23:02:00 +01:00
commit 9964446e5e
7 changed files with 4974 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/target
Cargo.lock

6
Cargo.toml Normal file
View File

@@ -0,0 +1,6 @@
[package]
name = "rust-aoc-2025"
version = "0.1.0"
edition = "2024"
[dependencies]

2
mise.toml Normal file
View File

@@ -0,0 +1,2 @@
[tools]
rust = "latest"

177
src/day1/dial_position.rs Normal file
View File

@@ -0,0 +1,177 @@
pub struct DialPosition {
pub current_position: i16,
pub zero_hits_count: u32,
}
impl DialPosition {
const DIAL_MAX: i16 = 99;
const DIAL_COUNT: i16 = 100;
pub fn new(current_position: i16) -> Self {
Self {
current_position,
zero_hits_count: 0,
}
}
pub fn rotated_left(&self, rotation: u64) -> Self {
let (remaining, reduce_hits_count) = DialPosition::reduce_rotation(rotation);
let current_position_u64 = self.current_position;
let (result, clamp_hits_count) = self.clamp(current_position_u64 - remaining);
Self {
current_position: result,
zero_hits_count: self.zero_hits_count + clamp_hits_count + reduce_hits_count,
}
}
pub fn rotated_right(&self, rotation: u64) -> Self {
let (remaining, reduce_hits_count) = DialPosition::reduce_rotation(rotation);
let (result, clamp_hits_count) = self.clamp(self.current_position + remaining);
Self {
current_position: result,
zero_hits_count: self.zero_hits_count + clamp_hits_count + reduce_hits_count,
}
}
fn reduce_rotation(rotation: u64) -> (i16, u32) {
let mut remaining = rotation;
let mut zero_hits_count = 0;
while remaining > u64::try_from(DialPosition::DIAL_MAX).unwrap() {
remaining -= u64::try_from(DialPosition::DIAL_COUNT).unwrap();
zero_hits_count += 1;
}
(i16::try_from(remaining).unwrap(), zero_hits_count)
}
fn clamp(&self, value: i16) -> (i16, u32) {
if value > DialPosition::DIAL_MAX {
(value - 100, 1)
} else if value < 0 {
(100 + value, if self.current_position != 0 { 1 } else { 0 })
} else {
(value, if value == 0 { 1 } else { 0 })
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dial_rotated_right_from_0_by_2_gives_2() {
let result = DialPosition::new(0).rotated_right(2);
assert_eq!(result.current_position, 2);
}
#[test]
fn dial_rotated_right_from_0_by_102_gives_2() {
let result = DialPosition::new(0).rotated_right(102);
assert_eq!(result.current_position, 2);
}
#[test]
fn dial_rotated_left_from_0_by_2_gives_98() {
let result = DialPosition::new(0).rotated_left(2);
assert_eq!(result.current_position, 98);
}
#[test]
fn dial_rotated_left_from_0_by_102_gives_98() {
let result = DialPosition::new(0).rotated_left(102);
assert_eq!(result.current_position, 98);
}
#[test]
fn dial_rotated_left_from_5_by_105_gives_0() {
let result = DialPosition::new(5).rotated_left(105);
assert_eq!(result.current_position, 0);
}
#[test]
fn dial_rotated_right_from_5_by_105_gives_10() {
let result = DialPosition::new(5).rotated_right(105);
assert_eq!(result.current_position, 10);
}
}
// part 2
#[test]
fn dial_from_50_right_1000_hits_zero_10_times() {
let result = DialPosition::new(50).rotated_right(1000);
assert_eq!(result.current_position, 50);
assert_eq!(result.zero_hits_count, 10);
}
#[test]
fn dial_from_50_left_68_hits_zero_once() {
let result = DialPosition::new(50).rotated_left(68);
assert_eq!(result.current_position, 82);
assert_eq!(result.zero_hits_count, 1);
}
#[test]
fn dial_from_82_left_30_no_zero_hit() {
let result = DialPosition::new(82).rotated_left(30);
assert_eq!(result.current_position, 52);
assert_eq!(result.zero_hits_count, 0);
}
#[test]
fn dial_from_52_right_48_lands_on_zero() {
let result = DialPosition::new(52).rotated_right(48);
assert_eq!(result.current_position, 0);
assert_eq!(result.zero_hits_count, 1);
}
#[test]
fn dial_from_0_left_5_no_zero_hit() {
let result = DialPosition::new(0).rotated_left(5);
assert_eq!(result.current_position, 95);
assert_eq!(result.zero_hits_count, 0);
}
#[test]
fn dial_from_95_right_60_hits_zero_once() {
let result = DialPosition::new(95).rotated_right(60);
assert_eq!(result.current_position, 55);
assert_eq!(result.zero_hits_count, 1);
}
#[test]
fn dial_from_55_left_55_lands_on_zero() {
let result = DialPosition::new(55).rotated_left(55);
assert_eq!(result.current_position, 0);
assert_eq!(result.zero_hits_count, 1);
}
#[test]
fn dial_from_0_left_1_no_zero_hit() {
let result = DialPosition::new(0).rotated_left(1);
assert_eq!(result.current_position, 99);
assert_eq!(result.zero_hits_count, 0);
}
#[test]
fn dial_from_99_left_99_lands_on_zero() {
let result = DialPosition::new(99).rotated_left(99);
assert_eq!(result.current_position, 0);
assert_eq!(result.zero_hits_count, 1);
}
#[test]
fn dial_from_0_right_14_no_zero_hit() {
let result = DialPosition::new(0).rotated_right(14);
assert_eq!(result.current_position, 14);
assert_eq!(result.zero_hits_count, 0);
}
#[test]
fn dial_from_14_left_82_hits_zero_once() {
let result = DialPosition::new(14).rotated_left(82);
assert_eq!(result.current_position, 32);
assert_eq!(result.zero_hits_count, 1);
}

4753
src/day1/input.txt Normal file

File diff suppressed because it is too large Load Diff

29
src/day1/mod.rs Normal file
View File

@@ -0,0 +1,29 @@
use std::fs;
mod dial_position;
pub fn solve_part1() {
let file = fs::read_to_string("src/day1/input.txt").expect("You didn't provide input.txt.");
let mut dial = dial_position::DialPosition::new(50);
let mut zero_position_occurences = 0;
for line in file.lines() {
let mut chars = line.chars();
if let Some(direction_string) = chars.nth(0) {
let value = String::from(chars.as_str())
.parse::<u64>()
.expect("This value is not a number");
if direction_string == 'L' {
dial = dial.rotated_left(value);
} else {
dial = dial.rotated_right(value);
}
if dial.current_position == 0 {
zero_position_occurences += 1
}
};
}
println!("The solution for part 1 is {}", zero_position_occurences);
println!("The solution for part 2 is {}", dial.zero_hits_count);
}

5
src/main.rs Normal file
View File

@@ -0,0 +1,5 @@
mod day1;
fn main() {
day1::solve_part1();
}