diff --git a/day_02/src/main.rs b/day_02/src/main.rs index 34ee732..8fac0f4 100644 --- a/day_02/src/main.rs +++ b/day_02/src/main.rs @@ -21,78 +21,113 @@ where } #[derive(Eq, PartialEq)] -enum LevelTransitionState { - Asc, - Desc, - Bad, - Dampened, +enum TransitionState { + Good, // Good state + Bad, // Bad state + Dampened, // Could be removed to make a good state } -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; - // If the diff is 0 or greater than 3, return bad stat - if level_diff == 0 || level_diff.abs() > 3 { - return LevelTransitionState::Bad; - } + // If the diff is 0 or greater than 3, return bad state + let state = if level_diff == 0 || level_diff.abs() > 3 { + TransitionState::Bad + } else { + TransitionState::Good + }; + // If great than zero they are ascending - if level_diff > 0 { - return LevelTransitionState::Asc; - } - //Else we're descending - return LevelTransitionState::Desc; + let direction = if level_diff > 0 { + TransitionDirection::Asc + } else { + TransitionDirection::Desc + }; + + return LevelTransition { state, direction }; } -fn is_report_safe(report: Vec) -> bool { +fn is_report_safe_no_dampening(report: Vec) -> bool { // Turn the report into a bunch of states for each adjacent pair in the report - let report: Vec = report + let report: Vec = 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 { + let mut prev_transition = &report[0]; + if prev_transition.state != TransitionState::Good { return false; } // 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 level_state == &LevelTransitionState::Bad { + if level_transition.state != TransitionState::Good { return false; } // If the states aren't the same as the prev, it must // have changed direction - if level_state != prev_state { + if level_transition.direction != prev_transition.direction { return false; } // Setup for next iteration - prev_state = level_state; + prev_transition = level_transition; } return true; } -// let mut modified_report: Vec> = vec![None]; -// let mut tmp_report: Vec> = report.iter().map(|v| Some(*v)).collect(); -// modified_report.append(&mut tmp_report); -// modified_report.push(None); -// dbg!(modified_report); +// fn is_report_safe_with_dampening(report: Vec) -> bool { +// let mut modified_report: Vec> = vec![None]; +// let mut tmp_report: Vec> = report.iter().map(|v| Some(*v)).collect(); +// modified_report.append(&mut tmp_report); +// modified_report.push(None); -// 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!"), +// 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)) | (Some(curr), Some(next), None) => { +// // Matched first or last element, which means we only have one check to do +// // and we always return Dampened instead of Bad +// let local_state = compare_levels(curr, next); +// if local_state == TransitionState::Bad { +// // 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> { @@ -109,16 +144,19 @@ fn main() -> Result<(), Box> { let input_file = File::open(input_file_string)?; let input_reader = BufReader::new(input_file); - let mut accumulator = 0; + let mut accumulator_no_dampening = 0; for line in input_reader.lines() { let line = line?; let parsed_report: Vec = parse_report(&line)?; - if is_report_safe(parsed_report) { - accumulator += 1; + if is_report_safe_no_dampening(parsed_report) { + accumulator_no_dampening += 1; } } - println!("Number of SAFE reports: {}", accumulator); + println!( + "Number of SAFE reports (No Dampening - Part 1): {}", + accumulator_no_dampening + ); Ok(()) }