split direction (asc/desc) from state (Good/Bad/Dampening)

This commit is contained in:
2025-05-25 18:06:17 -05:00
parent e2135b4684
commit 1510c09b01

View File

@@ -21,78 +21,113 @@ where
} }
#[derive(Eq, PartialEq)] #[derive(Eq, PartialEq)]
enum LevelTransitionState { enum TransitionState {
Asc, Good, // Good state
Desc, Bad, // Bad state
Bad, Dampened, // Could be removed to make a good state
Dampened,
} }
fn compare_levels(curr_level: i64, next_level: i64) -> LevelTransitionState { #[derive(Eq, PartialEq)]
enum TransitionDirection {
Asc, // level is increasing
Desc, // level is decreasing
}
struct LevelTransition {
state: TransitionState,
direction: TransitionDirection,
}
/// Given two level inputs, return one of the following:
/// - `LevelTransitionState::Bad` if the difference between
/// the levels is either 0 or great than 3
/// - `LevelTransitionState::Asc` if the value from curr_level to next_level is increasing and it's not BAD
/// - `LevelTransitionState::Desc` if the value from curr_level to next_level is decreasing and it's not BAD
fn compare_levels(curr_level: i64, next_level: i64) -> LevelTransition {
let level_diff = next_level - curr_level; let level_diff = next_level - curr_level;
// If the diff is 0 or greater than 3, return bad stat // If the diff is 0 or greater than 3, return bad state
if level_diff == 0 || level_diff.abs() > 3 { let state = if level_diff == 0 || level_diff.abs() > 3 {
return LevelTransitionState::Bad; TransitionState::Bad
} } else {
TransitionState::Good
};
// If great than zero they are ascending // If great than zero they are ascending
if level_diff > 0 { let direction = if level_diff > 0 {
return LevelTransitionState::Asc; TransitionDirection::Asc
} } else {
//Else we're descending TransitionDirection::Desc
return LevelTransitionState::Desc; };
return LevelTransition { state, direction };
} }
fn is_report_safe(report: Vec<i64>) -> bool { fn is_report_safe_no_dampening(report: Vec<i64>) -> bool {
// Turn the report into a bunch of states for each adjacent pair in the report // Turn the report into a bunch of states for each adjacent pair in the report
let report: Vec<LevelTransitionState> = report let report: Vec<LevelTransition> = report
.windows(2) .windows(2)
.map(|l| compare_levels(l[0], l[1])) .map(|l| compare_levels(l[0], l[1]))
.collect(); .collect();
// Setup the loop by checking the first start as a special case // Setup the loop by checking the first start as a special case
let mut prev_state = &report[0]; let mut prev_transition = &report[0];
if prev_state == &LevelTransitionState::Bad { if prev_transition.state != TransitionState::Good {
return false; return false;
} }
// Check each state // Check each state
for level_state in report[1..].iter() { for level_transition in report[1..].iter() {
// If bad, then it's just bad // If bad, then it's just bad
if level_state == &LevelTransitionState::Bad { if level_transition.state != TransitionState::Good {
return false; return false;
} }
// If the states aren't the same as the prev, it must // If the states aren't the same as the prev, it must
// have changed direction // have changed direction
if level_state != prev_state { if level_transition.direction != prev_transition.direction {
return false; return false;
} }
// Setup for next iteration // Setup for next iteration
prev_state = level_state; prev_transition = level_transition;
} }
return true; return true;
} }
// let mut modified_report: Vec<Option<i64>> = vec![None]; // fn is_report_safe_with_dampening(report: Vec<i64>) -> bool {
// let mut tmp_report: Vec<Option<i64>> = report.iter().map(|v| Some(*v)).collect(); // let mut modified_report: Vec<Option<i64>> = vec![None];
// modified_report.append(&mut tmp_report); // let mut tmp_report: Vec<Option<i64>> = report.iter().map(|v| Some(*v)).collect();
// modified_report.push(None); // modified_report.append(&mut tmp_report);
// dbg!(modified_report); // modified_report.push(None);
// let states = Vec::new(); // let states = Vec::new();
// for window in modified_report.windows(3) { // for window in modified_report.windows(3) {
// let window_tuple = (window[0], window[1], window[2]); // let window_tuple = (window[0], window[1], window[2]);
// let state = match window_tuple { // let state = match window_tuple {
// (None, Some(curr), Some(next)) => { // (None, Some(curr), Some(next)) | (Some(curr), Some(next), None) => {
// let diff = curr // // Matched first or last element, which means we only have one check to do
// }, // // and we always return Dampened instead of Bad
// (Some(prev), Some(curr), Some(next)) => (), // let local_state = compare_levels(curr, next);
// (Some(prev), Some(curr), None) => (), // if local_state == TransitionState::Bad {
// _ => panic!("This should never happen!"), // // shadow bad with dampened since can always
// // remove the first and last element.
// TransitionState::Dampened
// } else {
// local_state
// }
// },
// (Some(prev), Some(curr), Some(next)) => {
// let first_state = compare_levels(prev, curr);
// let second_state = compare_levels(curr, next);
// if first_state == TransitionState::Bad || second_state == TransitionState::Bad || first_state != second_state {
// }
// },
// _ => panic!("This should never happen!"),
// }
// states.push(state);
// } // }
// states.push(state); // true
// } // }
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
@@ -109,16 +144,19 @@ fn main() -> Result<(), Box<dyn Error>> {
let input_file = File::open(input_file_string)?; let input_file = File::open(input_file_string)?;
let input_reader = BufReader::new(input_file); let input_reader = BufReader::new(input_file);
let mut accumulator = 0; let mut accumulator_no_dampening = 0;
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_no_dampening(parsed_report) {
accumulator += 1; accumulator_no_dampening += 1;
} }
} }
println!("Number of SAFE reports: {}", accumulator); println!(
"Number of SAFE reports (No Dampening - Part 1): {}",
accumulator_no_dampening
);
Ok(()) Ok(())
} }