Day 1
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "rust-aoc-2025"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
177
src/day1/dial_position.rs
Normal file
177
src/day1/dial_position.rs
Normal 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
4753
src/day1/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
29
src/day1/mod.rs
Normal file
29
src/day1/mod.rs
Normal 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
5
src/main.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod day1;
|
||||
|
||||
fn main() {
|
||||
day1::solve_part1();
|
||||
}
|
||||
Reference in New Issue
Block a user