use std::fmt::Display; use advent_of_code::strings::{convert_to_array, parsenumber}; #[allow(unused_imports)] use advent_of_code_macros::{include_data, include_example}; include_data!(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 = convert_to_array(DATA, 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}") }