adventofcode/days/2024/02.rs

102 Zeilen
2,3 KiB
Rust

use advent_of_code::include_aoc;
use advent_of_code::{
strings::{convert_to_array, parsenumber},
KD,
};
include_aoc!(2024, 02);
fn get_numbers(input: &str) -> Vec<u32> {
input.split(char::is_whitespace).map(parsenumber).collect()
}
trait SafeCheck {
fn safe(&self) -> bool;
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
struct Record(Vec<u32>);
impl SafeCheck for Record {
fn safe(&self) -> bool {
safe(self.0.clone())
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
struct DampenedRecord(Vec<u32>);
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<u32>) -> 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 {
KD::Top
} else {
KD::Bottom
};
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) {
(KD::Top, false) | (KD::Bottom, true) => last = level,
(KD::Top, true) | (KD::Bottom, false) => errors += 1,
_ => unreachable!(),
}
}
if errors > 0 {
false
} else {
true
}
}
fn main() {
let numbers = convert_to_array::<_, _, '\n'>(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;
}
}
println!("Safe Reports: {safe_reports}");
println!("Safe Reports with dampener: {safe_with_dampener}")
}