From 1c4b2188f1658430de041b4f27d1d30ea449d0e7 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 1 Dec 2025 19:44:15 +0200 Subject: [PATCH] Finish part-01 --- 2025/day-01/src/part2.rs | 113 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 5 deletions(-) diff --git a/2025/day-01/src/part2.rs b/2025/day-01/src/part2.rs index cbcdee4..e4cdf25 100644 --- a/2025/day-01/src/part2.rs +++ b/2025/day-01/src/part2.rs @@ -1,9 +1,103 @@ use miette::Result; +use std::str::FromStr; + +#[derive(Debug, Clone, Copy, PartialEq)] +enum Direction { + Left, + Right, +} + +impl FromStr for Direction { + type Err = String; + fn from_str(s: &str) -> std::result::Result { + match s.to_lowercase().trim() { + "l" => Ok(Self::Left), + "r" => Ok(Self::Right), + _ => Err("Wrong value".to_string()), + } + } +} + +#[derive(Debug, Clone, Copy)] +struct Rotation { + amount: i32, + direction: Direction, +} + +impl FromStr for Rotation { + type Err = String; + fn from_str(s: &str) -> std::result::Result { + let trimmed = s.trim(); + let (direction_str, amount_str) = trimmed.split_at(1); + let direction = direction_str.parse()?; + let amount = amount_str.parse::().map_err(|e| e.to_string())?; + + Ok(Self { amount, direction }) + } +} + +#[derive(Debug, Clone)] +struct Sequence { + rotations: Vec, +} + +impl FromStr for Sequence { + type Err = String; + fn from_str(s: &str) -> std::result::Result { + let rotations = s + .trim() + .lines() + .map(|line| line.parse::().unwrap()) + .collect::>(); + Ok(Self { rotations }) + } +} #[tracing::instrument] +#[allow(clippy::missing_panics_doc)] +#[allow(clippy::missing_errors_doc)] pub fn process(input: &str) -> Result { - todo!("day xx - part 2"); - Ok(0) + let sequence = input.parse::().unwrap(); + let (_, total_zeros) = sequence + .rotations + .iter() + .fold((50, 0), |(dial, total), rotation| { + let new_dial = match rotation.direction { + Direction::Left => (dial - rotation.amount).rem_euclid(100), + Direction::Right => (dial + rotation.amount).rem_euclid(100), + }; + + let zeros_crossed = count_zeros_crossed(dial, rotation.amount, rotation.direction); + let new_total = total + zeros_crossed; + (new_dial, new_total) + }); + Ok(total_zeros.try_into().unwrap()) +} + +const fn count_zeros_crossed(pos: i32, amount: i32, direction: Direction) -> i32 { + match direction { + Direction::Left => { + if pos == 0 { + amount / 100 + } else if amount >= pos { + 1 + (amount - pos) / 100 + } else { + 0 + } + } + Direction::Right => { + if pos == 0 { + amount / 100 + } else { + let target = 100 - pos; + if amount >= target { + 1 + (amount - target) / 100 + } else { + 0 + } + } + } + } } #[cfg(test)] @@ -12,9 +106,18 @@ mod tests { #[test] fn test_process() -> Result<()> { - let input = ""; - todo!("haven't built test yet"); - let result = 0; + let input = "L68 +L30 +R48 +L5 +R60 +L55 +L1 +L99 +R14 +L82 +"; + let result = 6; assert_eq!(process(input)?, result); Ok(()) }