Incorrect day 2 part 2 implementation
This commit is contained in:
@@ -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
|
||||
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<i64>) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
// fn is_report_safe_with_dampening(report: Vec<i64>) -> bool {
|
||||
// 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);
|
||||
fn is_report_safe_with_dampening(report: Vec<i64>) -> bool {
|
||||
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);
|
||||
|
||||
// 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<dyn Error>> {
|
||||
// Handle command input
|
||||
@@ -145,18 +223,31 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
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<i64> = 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(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user