diff --git a/crates/day_1/data/input b/crates/day_1/data/day1_input similarity index 100% rename from crates/day_1/data/input rename to crates/day_1/data/day1_input diff --git a/crates/day_1/data/test_input b/crates/day_1/data/day1_test_input similarity index 100% rename from crates/day_1/data/test_input rename to crates/day_1/data/day1_test_input diff --git a/crates/day_1/src/day_1.rs b/crates/day_1/src/day_1.rs index 560a2cc..d37b8b1 100644 --- a/crates/day_1/src/day_1.rs +++ b/crates/day_1/src/day_1.rs @@ -105,6 +105,7 @@ impl Solver for Day1 fn init(self: &mut Self, data_set: DataSet, run_mode: RunMode, enable_debug_prints: bool) { + self.data_set = data_set; self.run_mode = run_mode; self.do_debug_prints = enable_debug_prints; @@ -112,8 +113,8 @@ impl Solver for Day1 let data_filename = match self.data_set { - DataSet::Test => format!("{}/data/test_input", dir), - DataSet::Full => format!("{}/data/input", dir), + DataSet::Test => format!("{}/data/day1_test_input", dir), + DataSet::Full => format!("{}/data/day1_input", dir), }; @@ -139,6 +140,11 @@ impl Solver for Day1 self.data_a.sort(); self.data_b.sort(); + if self.data_a.len() != self.data_b.len() + { + panic!("Day 1 ERROR: Data set lengths do NOT match: data_a.len(): {}, data_b.len(): {}", self.data_a.len(), self.data_b.len()); + } + if self.do_debug_prints { println!("Day1 Debug: Input data processed:\n\tdata_a: {:#?}\n\tdata_b: {:#?}", self.data_a, self.data_b); diff --git a/crates/day_2/data/input b/crates/day_2/data/day2_input.txt similarity index 100% rename from crates/day_2/data/input rename to crates/day_2/data/day2_input.txt diff --git a/crates/day_2/data/test_input b/crates/day_2/data/day2_test_input similarity index 100% rename from crates/day_2/data/test_input rename to crates/day_2/data/day2_test_input diff --git a/crates/day_2/src/day_2.rs b/crates/day_2/src/day_2.rs index 7ad9bc6..40ae22f 100644 --- a/crates/day_2/src/day_2.rs +++ b/crates/day_2/src/day_2.rs @@ -8,7 +8,7 @@ * @brief Advent of Code 2024 day 2 problems ******************************************************************************/ -use crate::report::Report; +use crate::report::{Report, Status}; use ::solver_base::solver_base::{Solver, DataSet, RunMode}; use utils::utils; @@ -30,20 +30,6 @@ impl Day2 { Day2 { data_set: DataSet::Test, run_mode: RunMode::FirstCase, do_debug_prints: false, reports: vec![], final_result: 0 } } - - fn solve_first_case(self: &mut Self) -> String - { - // TODO: Day2::solve_first_case - - self.final_result.to_string() - } - - fn solve_second_case(self: &mut Self) -> String - { - // TODO: Day2::solve_second_case - - self.final_result.to_string() - } } //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| @@ -58,6 +44,7 @@ impl Solver for Day2 fn init(self: &mut Self, data_set: DataSet, run_mode: RunMode, enable_debug_prints: bool) { + self.data_set = data_set; self.run_mode = run_mode; self.do_debug_prints = enable_debug_prints; @@ -65,8 +52,8 @@ impl Solver for Day2 let data_filename = match self.data_set { - DataSet::Test => format!("{}/data/test_input", dir), - DataSet::Full => format!("{}/data/input", dir), + DataSet::Test => format!("{}/data/day2_test_input", dir), + DataSet::Full => format!("{}/data/day2_input", dir), }; @@ -78,6 +65,15 @@ impl Solver for Day2 println!("Raw report: {}", r); } + if r.is_empty() + { + if self.do_debug_prints + { + println!("Day 2 DEBUG: Report is empty, discarding..."); + } + continue; + } + let mut lvl_list: Vec = vec![]; for value in r.split(" ") { @@ -89,25 +85,26 @@ impl Solver for Day2 println!("Processed report: {:#?}", lvl_list); } - self.reports.push(Report::new(lvl_list)); + let dampener = self.run_mode == RunMode::SecondCase; + self.reports.push(Report::new(lvl_list, dampener)); } } fn solve(self: &mut Self) -> String { - match self.run_mode + let mut num_safe = 0; + for report in &mut self.reports { - RunMode::FirstCase => + if report.analyze(self.do_debug_prints) == Status::Safe { - self.solve_first_case() - }, - - RunMode::SecondCase => - { - self.solve_second_case() + num_safe += 1; } } + + self.final_result = num_safe; + + self.final_result.to_string() } } \ No newline at end of file diff --git a/crates/day_2/src/report.rs b/crates/day_2/src/report.rs index ea765b3..62eae1b 100644 --- a/crates/day_2/src/report.rs +++ b/crates/day_2/src/report.rs @@ -13,19 +13,105 @@ pub struct Report { levels: Vec, status: Status, + enable_dampener: bool, + dampen_count: i32, } impl Report { - pub fn new(lvls: Vec) -> Report + pub fn new(lvls: Vec, enable_dampener: bool) -> Report { - Report { levels: lvls , status: Status::Unknown } + Report { levels: lvls , status: Status::Unknown, enable_dampener, dampen_count: 0 } } - pub fn analyze(self: &mut Report) -> Status + // SAFTY RULES: + // The levels are either all increasing or all decreasing. + // Any two adjacent levels differ by at least one and at most three. + + pub fn analyze(self: &mut Report, enable_debug_prints: bool) -> Status { - // TODO: Report::analyze() + let mut prev_direction = 0; + let mut i = 0; + while i < self.levels.len() - 1 // Don't process the last level value + { + let diff = self.levels[i] - self.levels[i + 1]; + let this_direction = if diff > 0 { 1 } else if diff < 0 { -1 } else { 0 }; + + // diff check + let diff = diff.abs(); + if diff > 3 || diff < 1 + { + if self.dampen_level(i + 1, enable_debug_prints) + { + i = 0; + continue; + } + + if enable_debug_prints + { + println!("Day 2 DEBUG: Report ({:#?}) is unsafe due to invalid value gap ({}): {} to {}", self.levels, diff, self.levels[i], self.levels[i + 1]) + } + self.status = Status::Unsafe; + return self.status; + } + + // increase/decrease check + if 0 == prev_direction + { + prev_direction = this_direction + } + else + { + if prev_direction != this_direction + { + if self.dampen_level(i, enable_debug_prints) + { + i = 0; + continue; + } + + if enable_debug_prints + { + println!("Day 2 DEBUG: Report ({:#?}) is unsafe due to increase/decrease rule violation: {} to {}", self.levels, self.levels[i], self.levels[i + 1]) + } + self.status = Status::Unsafe; + return self.status; + } + } + + i += 1; + } + self.status = Status::Safe; + return self.status; + } + + fn check_levels(self: &mut Report, enable_debug_prints: bool) -> Status + { Status::Unknown } + + fn dampen_level(self: &mut Report, at: usize, do_debug_prints: bool) -> bool + { + if !self.enable_dampener + { + return false; + } + + if do_debug_prints + { + println!("Day 2 DEBUG: Bad level detected in report ({:#?}), using dampener to remove level: {}", self.levels, self.levels[at]); + } + + self.levels.remove(at); + self.enable_dampener = false; + self.dampen_count += 1; + + if self.dampen_count > 1 + { + panic!("Day 2 ERROR: Dampener used more than once! usage: {}", self.dampen_count); + } + + return true; + } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e7afca8..0d0c1e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,8 +27,13 @@ fn main() // DAY 2 let mut day_2 = Day2::new(); - day_2.init(DataSet::Full, RunMode::FirstCase, true); + day_2.init(DataSet::Full, RunMode::FirstCase, false); let day2_result = day_2.solve(); println!("Day2 Part 1 Final Result: {}", day2_result); + let mut day_2 = Day2::new(); + day_2.init(DataSet::Full, RunMode::SecondCase, false); + let day2_result = day_2.solve(); + println!("Day2 Part 2 Final Result: {}", day2_result); + }