From 45c5a7a1dfe4a8108cf53ca68a6eabfeb3a5bd14 Mon Sep 17 00:00:00 2001 From: Bearmine Date: Sun, 25 May 2025 19:27:15 -0500 Subject: [PATCH] Incorrect day 2 part 2 implementation --- day_02/src/main.rs | 169 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 130 insertions(+), 39 deletions(-) diff --git a/day_02/src/main.rs b/day_02/src/main.rs index 8fac0f4..f381459 100644 --- a/day_02/src/main.rs +++ b/day_02/src/main.rs @@ -20,19 +20,21 @@ where Ok(parsed_line) } -#[derive(Eq, PartialEq)] +#[derive(Eq, PartialEq, Copy, Clone, Debug)] enum TransitionState { - Good, // Good state - Bad, // Bad state - Dampened, // Could be removed to make a good state + Good, // Good state + Bad, // Bad state + Dampened, // Could be removed to make a good state + DampenedEnd, // Could be removed to make a good state, end or start of report } -#[derive(Eq, PartialEq)] +#[derive(Eq, PartialEq, Copy, Clone, Debug)] enum TransitionDirection { Asc, // level is increasing Desc, // level is decreasing } +#[derive(Debug)] struct LevelTransition { state: TransitionState, direction: TransitionDirection, @@ -94,41 +96,117 @@ fn is_report_safe_no_dampening(report: Vec) -> bool { return true; } -// 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); +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)) | (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 { + let mut transitions = Vec::new(); + for window in modified_report.windows(3) { + let window_tuple = (window[0], window[1], window[2]); + let state = match window_tuple { + // We loop through in 3 value windows. We padded a None on + // either side of the vec to detect the ends of the report for special handling. + // + // If the middle value from the window could be removed to make that section of repo SAFE, + //mark as Dempened. We will use this later to determine if there's only a single dampened + //value we can remove to meet the dampening criteria. + (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_transition = compare_levels(curr, next); + if local_transition.state == TransitionState::Bad { + // shadow bad with dampened since can always + // remove the first and last element. + LevelTransition { + state: TransitionState::DampenedEnd, + ..local_transition + } + } else { + local_transition + } + } + (Some(prev), Some(curr), Some(next)) => { + let first_transition = compare_levels(prev, curr); + let second_transition = compare_levels(curr, next); + if first_transition.state != TransitionState::Good + || second_transition.state != TransitionState::Good + || first_transition.direction != second_transition.direction + { + let jump_transition = compare_levels(prev, next); + if jump_transition.state == TransitionState::Good { + //println!("Dampening value window: {:?}", window_tuple); + // If we removed the middle value, we would be in a SAFE state, mark as DAMPENED + LevelTransition { + state: TransitionState::Dampened, + ..jump_transition + } + } else { + // Removing the middle value does not help us. mark as BAD + LevelTransition { + state: TransitionState::Bad, + ..jump_transition + } + } + } else { + // Both transitions are good and moving in the same directions, so we can return either. + second_transition + } + } + _ => panic!("This should never happen!"), + }; + transitions.push(state); + } -// } -// }, -// _ => panic!("This should never happen!"), -// } -// states.push(state); -// } -// true -// } + let (mut dampened_cnt, mut prev_direction) = match transitions[0].state { + TransitionState::Good => (0, transitions[0].direction), + TransitionState::Dampened | TransitionState::DampenedEnd => (1, transitions[1].direction), + TransitionState::Bad => { + panic!("This should never happen!"); + } + }; + for transition in &transitions { + match transition.state { + TransitionState::Good => { + if transition.direction != prev_direction { + println!( + "Failed for non matching direction: {:?} -> {:?}", + report, transitions + ); + return false; + } + } + TransitionState::Dampened => { + dampened_cnt += 1; + if transition.direction != prev_direction { + println!( + "Failed for non matching direction: {:?} -> {:?}", + report, transitions + ); + return false; + } + } + TransitionState::DampenedEnd => { + dampened_cnt += 1; + } + TransitionState::Bad => { + // If it's marked as bad we can't fix it by dampening, return false + return false; + } + } + // We can only dampen one value + if dampened_cnt > 1 { + println!( + "Failed for too much dampening: {:?} -> {:?}", + report, transitions + ); + return false; + } + prev_direction = transition.direction; + } + true +} fn main() -> Result<(), Box> { // Handle command input @@ -145,18 +223,31 @@ fn main() -> Result<(), Box> { let input_reader = BufReader::new(input_file); let mut accumulator_no_dampening = 0; + let mut accumulator_with_dampening = 0; for line in input_reader.lines() { let line = line?; let parsed_report: Vec = parse_report(&line)?; - if is_report_safe_no_dampening(parsed_report) { + if is_report_safe_no_dampening(parsed_report.clone()) { accumulator_no_dampening += 1; } + if is_report_safe_with_dampening(parsed_report) { + accumulator_with_dampening += 1; + } } + println!( + "test: {}", + is_report_safe_with_dampening(vec![1, 3, 2, 4, 5]) + ); + println!( "Number of SAFE reports (No Dampening - Part 1): {}", accumulator_no_dampening ); + println!( + "Number of SAFE reports (With Dampening - Part 2): {}", + accumulator_with_dampening + ); Ok(()) }