81 lines
1.9 KiB
Rust
81 lines
1.9 KiB
Rust
|
|
use advent_of_code_2024::{make_main, SResult};
|
||
|
|
|
||
|
|
make_main!();
|
||
|
|
|
||
|
|
// CODE
|
||
|
|
#[derive(PartialEq, Clone, Copy)]
|
||
|
|
enum Direction {
|
||
|
|
Up,
|
||
|
|
Down,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Direction {
|
||
|
|
fn from(a: usize, b: usize) -> Self {
|
||
|
|
if a > b {
|
||
|
|
Direction::Down
|
||
|
|
} else {
|
||
|
|
Direction::Up
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fn solve(lines: Vec<String>) -> SResult<usize> {
|
||
|
|
let mut fail_count = 0;
|
||
|
|
for line in lines.iter() {
|
||
|
|
let reports: Vec<usize> = line
|
||
|
|
.split_whitespace()
|
||
|
|
.map(|v| v.parse::<usize>().unwrap())
|
||
|
|
.collect();
|
||
|
|
let problems = match test(&reports) {
|
||
|
|
// Cool, nothing to see here
|
||
|
|
Ok(_) => continue,
|
||
|
|
Err(e) => e,
|
||
|
|
};
|
||
|
|
let mut pass = false;
|
||
|
|
for problem in problems {
|
||
|
|
let mut l1 = reports.clone();
|
||
|
|
l1.remove(problem);
|
||
|
|
if test(&l1).is_ok() {
|
||
|
|
pass = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if !pass {
|
||
|
|
fail_count += 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Ok(lines.len() - fail_count)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests the report, and returns indexes around where a failure is detected.
|
||
|
|
fn test(reports: &[usize]) -> Result<(), Vec<usize>> {
|
||
|
|
let mut i = 0;
|
||
|
|
let direction = Direction::from(reports[0], reports[1]);
|
||
|
|
while i + 1 < reports.len() {
|
||
|
|
let delta = reports[i].abs_diff(reports[i + 1]);
|
||
|
|
if delta < 1 || delta > 3 || direction != Direction::from(reports[i], reports[i + 1]) {
|
||
|
|
let mut errs = vec![i, i + 1];
|
||
|
|
if i > 0 {
|
||
|
|
errs.push(i - 1);
|
||
|
|
}
|
||
|
|
return Err(errs);
|
||
|
|
}
|
||
|
|
i += 1;
|
||
|
|
}
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
// CODE
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use advent_of_code_2024::input;
|
||
|
|
|
||
|
|
use super::*;
|
||
|
|
#[test]
|
||
|
|
fn sample_input() {
|
||
|
|
let strings: Vec<String> = input!("d2p1.txt");
|
||
|
|
let got = solve(strings).unwrap();
|
||
|
|
assert_eq!(got, 4);
|
||
|
|
}
|
||
|
|
}
|