Better report safety checking

This commit is contained in:
2025-05-25 17:15:31 -05:00
parent b4eea22e1b
commit e2135b4684
2 changed files with 74 additions and 32 deletions

View File

@@ -1,4 +1,4 @@
//https://adventofcode.com/2024/day/1 // https://adventofcode.com/2024/day/1
// //
// run command: `cargo run ./input.txt` // run command: `cargo run ./input.txt`

View File

@@ -1,4 +1,7 @@
use std::collections::HashMap; // https://adventofcode.com/2024/day/2
//
// run command: `cargo run ./input.txt`
use std::env; use std::env;
use std::error::Error; use std::error::Error;
use std::fs::File; use std::fs::File;
@@ -17,42 +20,81 @@ where
Ok(parsed_line) Ok(parsed_line)
} }
enum ReportDirection { #[derive(Eq, PartialEq)]
enum LevelTransitionState {
Asc, Asc,
Desc, Desc,
Bad,
Dampened,
} }
fn is_report_safe(report: &Vec<i64>) -> bool { fn compare_levels(curr_level: i64, next_level: i64) -> LevelTransitionState {
let direction = if report[0] < report[1] { let level_diff = next_level - curr_level;
ReportDirection::Asc
} else {
ReportDirection::Desc
};
match direction { // If the diff is 0 or greater than 3, return bad stat
ReportDirection::Asc => { if level_diff == 0 || level_diff.abs() > 3 {
let mut prev_report_level = report[0]; return LevelTransitionState::Bad;
for report_level in report[1..].iter() { }
if prev_report_level >= *report_level || report_level - prev_report_level > 3 { // If great than zero they are ascending
return false; if level_diff > 0 {
} return LevelTransitionState::Asc;
prev_report_level = *report_level; }
} //Else we're descending
} return LevelTransitionState::Desc;
ReportDirection::Desc => {
let mut prev_report_level = report[0];
for report_level in report[1..].iter() {
if prev_report_level <= *report_level || prev_report_level - report_level > 3 {
return false;
}
prev_report_level = *report_level;
}
}
};
true
} }
fn is_report_safe(report: Vec<i64>) -> bool {
// Turn the report into a bunch of states for each adjacent pair in the report
let report: Vec<LevelTransitionState> = report
.windows(2)
.map(|l| compare_levels(l[0], l[1]))
.collect();
// Setup the loop by checking the first start as a special case
let mut prev_state = &report[0];
if prev_state == &LevelTransitionState::Bad {
return false;
}
// Check each state
for level_state in report[1..].iter() {
// If bad, then it's just bad
if level_state == &LevelTransitionState::Bad {
return false;
}
// If the states aren't the same as the prev, it must
// have changed direction
if level_state != prev_state {
return false;
}
// Setup for next iteration
prev_state = level_state;
}
return true;
}
// let mut modified_report: Vec<Option<i64>> = vec![None];
// let mut tmp_report: Vec<Option<i64>> = report.iter().map(|v| Some(*v)).collect();
// modified_report.append(&mut tmp_report);
// modified_report.push(None);
// dbg!(modified_report);
// let states = Vec::new();
// for window in modified_report.windows(3) {
// let window_tuple = (window[0], window[1], window[2]);
// let state = match window_tuple {
// (None, Some(curr), Some(next)) => {
// let diff = curr
// },
// (Some(prev), Some(curr), Some(next)) => (),
// (Some(prev), Some(curr), None) => (),
// _ => panic!("This should never happen!"),
// }
// states.push(state);
// }
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
// Handle command input // Handle command input
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
@@ -71,7 +113,7 @@ fn main() -> Result<(), Box<dyn Error>> {
for line in input_reader.lines() { for line in input_reader.lines() {
let line = line?; let line = line?;
let parsed_report: Vec<i64> = parse_report(&line)?; let parsed_report: Vec<i64> = parse_report(&line)?;
if is_report_safe(&parsed_report) { if is_report_safe(parsed_report) {
accumulator += 1; accumulator += 1;
} }
} }