diff --git a/src/bin/2024/02.rs b/src/bin/2024/02.rs new file mode 100644 index 0000000..7c267d5 --- /dev/null +++ b/src/bin/2024/02.rs @@ -0,0 +1,120 @@ +use std::fmt::Display; + +use advent_of_code::strings::parsenumber; +#[allow(unused_imports)] +use adventofcode_macros::{include_data, include_example}; + +include_data!(2024 02); + +fn get_numbers(input: &str) -> Vec { + input.split(char::is_whitespace).map(parsenumber).collect() +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +enum Direction { + Up, + Down, +} + +impl Display for Direction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let _ = f.write_str(match *self { + Direction::Down => "Down", + Direction::Up => "Up", + }); + Ok(()) + } +} + +trait SafeCheck { + fn safe(&self) -> bool; +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +struct Record(Vec); + +impl SafeCheck for Record { + fn safe(&self) -> bool { + safe(self.0.clone()) + } +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +struct DampenedRecord(Vec); + +impl SafeCheck for DampenedRecord { + fn safe(&self) -> bool { + for i in 0..self.0.len() { + let mut c = self.0.clone(); + c.remove(i); + if safe(c) { + return true; + } + } + false + } +} + +fn safe(record: Vec) -> bool { + const MAX: u32 = 3; + let mut i = record.clone().into_iter(); + let mut ups = 0; + let mut downs = 0; + let mut last = i.next().unwrap(); + for level in i { + if last < level { + last = level; + ups += 1 + } else if last > level { + last = level; + downs += 1; + } else { + ups += 1; + downs += 1; + } + } + let direction = if ups > downs { + Direction::Up + } else { + Direction::Down + }; + let mut errors = 0; + i = record.clone().into_iter(); + last = i.next().unwrap(); + let mut diff: u32; + for level in i { + diff = last.abs_diff(level); + if diff > MAX || diff == 0 { + errors += 1; + continue; + } + match (direction, last > level) { + (Direction::Up, false) | (Direction::Down, true) => last = level, + (Direction::Up, true) | (Direction::Down, false) => errors += 1, + } + } + if errors > 0 { + false + } else { + true + } +} + +fn main() { + let numbers = DATA.split('\n').map(get_numbers); + let mut safe_reports = 0; + let mut safe_with_dampener = 0; + for report in numbers { + if Record(report.clone()).safe() { + safe_reports += 1; + } + if DampenedRecord(report.clone()).safe() { + safe_with_dampener += 1; + } + } + if safe_reports != 598 || safe_with_dampener == 623 { + println!("Broken implementation") + } + println!("Safe Reports: {safe_reports}"); + println!("Safe Reports with dampener: {safe_with_dampener}") +}