From cc2a0fa1c2762407317adb76fd1135b1db9a2ada Mon Sep 17 00:00:00 2001 From: Connor Glosser Date: Mon, 2 Dec 2024 13:46:58 -0500 Subject: [PATCH] Solve 2024 day 02 --- src/lib/solutions/year_2024/day_01.rs | 1 + src/lib/solutions/year_2024/day_02.rs | 107 ++++++++++++++++++++++++++ src/lib/solutions/year_2024/mod.rs | 2 + 3 files changed, 110 insertions(+) create mode 100644 src/lib/solutions/year_2024/day_02.rs diff --git a/src/lib/solutions/year_2024/day_01.rs b/src/lib/solutions/year_2024/day_01.rs index 47fa541..306b479 100644 --- a/src/lib/solutions/year_2024/day_01.rs +++ b/src/lib/solutions/year_2024/day_01.rs @@ -50,6 +50,7 @@ fn sorted_lists(input: &str) -> (Vec, Vec) { (left.into_sorted_vec(), right.into_sorted_vec()) } +#[allow(unused_imports)] mod tests { use super::*; diff --git a/src/lib/solutions/year_2024/day_02.rs b/src/lib/solutions/year_2024/day_02.rs new file mode 100644 index 0000000..a20b752 --- /dev/null +++ b/src/lib/solutions/year_2024/day_02.rs @@ -0,0 +1,107 @@ +use crate::utils::solution::Solution; + +/// Puzzle: https://adventofcode.com/2024/day/2/ +pub struct Day02 {} + +impl Solution for Day02 { + fn part_one(&self, input: &str) -> Option { + Some( + reports(input) + .iter() + .filter(|r| r.status() == Status::Safe) + .count() + .to_string(), + ) + } + + fn part_two(&self, input: &str) -> Option { + Some( + reports(input) + .iter() + .filter(|r| r.status() != Status::Unsafe) + .count() + .to_string(), + ) + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +enum Status { + Safe, + Dampened, + Unsafe, +} + +#[derive(Debug)] +struct Report { + levels: Vec, +} + +impl Report { + fn status(&self) -> Status { + fn is_safe + Clone>(mut values: T) -> bool { + values.clone().all(|delta| (1..=3).contains(&delta)) + || values.all(|delta| (-3..=-1).contains(&delta)) + } + + let deltas = (0..self.levels.len()).map(|i| { + let reduced = self + .levels + .iter() + .enumerate() + .filter(move |(n, _)| i != *n) + .map(|(_, x)| x); + + reduced.clone().zip(reduced.skip(1)).map(|(a, b)| b - a) + }); + + if is_safe( + self.levels + .iter() + .zip(self.levels.iter().skip(1)) + .map(|(a, b)| b - a), + ) { + Status::Safe + } else if deltas.clone().any(is_safe) { + Status::Dampened + } else { + Status::Unsafe + } + } +} + +impl From<&str> for Report { + fn from(value: &str) -> Self { + Report { + levels: value + .split_ascii_whitespace() + .flat_map(str::parse::) + .collect(), + } + } +} + +fn reports(input: &str) -> Vec { + input.lines().map(Into::into).collect() +} + +#[allow(unused_imports)] +mod tests { + use itertools::Itertools; + + use super::*; + + #[test] + fn example() { + const INPUT: &str = "7 6 4 2 1 +1 2 7 8 9 +9 7 6 2 1 +1 3 2 4 5 +8 6 4 4 1 +1 3 6 7 9 +"; + let day02 = Day02 {}; + assert_eq!(day02.part_one(INPUT), Some("2".to_string())); + assert_eq!(day02.part_two(INPUT), Some("4".to_string())); + } +} diff --git a/src/lib/solutions/year_2024/mod.rs b/src/lib/solutions/year_2024/mod.rs index eac2e6f..7a725ba 100644 --- a/src/lib/solutions/year_2024/mod.rs +++ b/src/lib/solutions/year_2024/mod.rs @@ -1,10 +1,12 @@ use super::DayAssociations; pub mod day_01; +pub mod day_02; pub fn solutions() -> DayAssociations { let associations: Vec<(i32, super::BoxedSolution)> = vec![ (1, Box::new(day_01::Day01 {})), + (2, Box::new(day_02::Day02 {})), ]; associations.into_iter().collect()