diff --git a/crates/day_5/src/day_5.rs b/crates/day_5/src/day_5.rs index 1d591a2..68fa2c2 100644 --- a/crates/day_5/src/day_5.rs +++ b/crates/day_5/src/day_5.rs @@ -19,6 +19,7 @@ pub struct Day5 pub final_result: i32, rules: Vec, + updates: Vec, } //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| @@ -28,19 +29,75 @@ impl Day5 { pub fn new() -> Day5 { - Day5 { data_set: DataSet::Test, run_mode: RunMode::FirstCase, do_debug_prints: false, final_result: 0, rules: vec![] } + Day5 { data_set: DataSet::Test, run_mode: RunMode::FirstCase, + do_debug_prints: false, final_result: 0, rules: vec![], updates: vec![] } } fn solve_first_case(self: &mut Self) -> String { + // verify all updates + let valid_count = check_updates(&mut self.updates, &self.rules, self.do_debug_prints); + + if self.do_debug_prints + { + println!("DEBUG: valid updates found: {}", valid_count); + } + + // Sum the middle page of each valid update + let mut sum = 0; + for update in &self.updates + { + if UpdateStatus::Valid == update.status + { + let mid_idx = update.pages.len() / 2; + sum += update.pages[mid_idx]; + } + } + self.final_result = sum; self.final_result.to_string() } fn solve_second_case(self: &mut Self) -> String { + // verify + let _ = check_updates(&mut self.updates, &self.rules, self.do_debug_prints); - + // fix any broken updates and sum their mid pages + let mut sum = 0; + for update in &mut self.updates + { + if UpdateStatus::Valid == update.status + { + continue; + } + + let mut fixed = false; + let mut i = 0; + while i < self.rules.len() + { + if !self.rules[i].verify_update(&update.pages, self.do_debug_prints) + { + self.rules[i].make_valid(&mut update.pages, self.do_debug_prints); + i = 0; + fixed = true; + } + else + { + i += 1; + } + } + + if fixed && self.do_debug_prints + { + println!("DEBUG: Fixed update: {:#?}", update.pages); + } + + let mid_idx = update.pages.len() / 2; + sum += update.pages[mid_idx]; + } + + self.final_result = sum; self.final_result.to_string() } } @@ -52,7 +109,7 @@ impl Solver for Day5 { fn print_test() { - println!("DAY 4 TEST PRINT"); + println!("DAY 5 TEST PRINT"); } fn init(self: &mut Self, data_set: DataSet, run_mode: RunMode, enable_debug_prints: bool) @@ -81,9 +138,35 @@ impl Solver for Day5 let data_split = data.split(split_pattern); for row in data_split { + if self.do_debug_prints + { + println!("DEBUG: Loading row: {}", row); + } + + if row.is_empty() + { + if self.do_debug_prints + { + println!("DEBUG: Skipping empty row"); + } + continue; + } + + // Rules contain "|", update lists do not if row.contains("|") { - self.rules.push(Rule::parse(row).expect(&format!("Failed to create rule from: {}", row) )); + self.rules.push(Rule::parse(row).expect(&format!("ERROR: Failed to create rule from: {}", row) )); + } + else + { + let mut pages: Vec = vec![]; + for page in row.split(",") + { + let page_i = page.parse::().expect(&format!("ERROR: Failed to parse update page: {}", page)); + pages.push(page_i); + } + + self.updates.push(Update::new(pages)); } } @@ -92,10 +175,23 @@ impl Solver for Day5 println!("Rules:"); for rule in &self.rules { - println!("\tRule: {}|{}", rule.first, rule.second); + println!("\t{}|{}", rule.first, rule.second); + } + + println!("Updates:"); + for update in &self.updates + { + print!("\t"); + for page in &update.pages + { + print!("{},", page); + } + println!(); } } + + } fn solve(self: &mut Self) -> String @@ -120,6 +216,30 @@ impl Solver for Day5 // EXTRA STUFF //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +fn check_updates(updates: &mut Vec, rules: &Vec, enable_debug_prints: bool) -> i32 +{ + let mut valid_count = 0; + for update in updates + { + for rules in rules + { + if !rules.verify_update(&update.pages, enable_debug_prints) + { + update.status = UpdateStatus::Invalid; + break; + } + } + + if UpdateStatus::Unknown == update.status + { + update.status = UpdateStatus::Valid; + valid_count += 1; + } + } + + return valid_count; +} + #[derive(Copy, Clone, Debug)] struct Rule { @@ -129,7 +249,7 @@ struct Rule impl Rule { - fn new(first: i32, second: i32) -> Rule + fn _new(first: i32, second: i32) -> Rule { Rule { first, second } } @@ -150,4 +270,79 @@ impl Rule Ok(Rule { first, second}) } + + fn verify_update(self: &Rule, update: &Vec, enable_debug_output: bool) -> bool + { + let mut found_second = false; + + for page in update + { + if *page == self.first + { + if found_second + { + if enable_debug_output + { + println!("DEBUG: Update ({:#?}) fails rule: {}|{} -- found first after second", update, self.first, self.second); + } + return false; + } + } + + if *page == self.second + { + found_second = true; + } + } + + return true; + } + + fn make_valid(self: &Rule, update: &mut Vec, enable_debug_output: bool) + { + let mut first_idx = 0; + let mut second_idx = 0; + + for (i, page) in update.iter().enumerate() + { + if *page == self.first + { + first_idx = i; + } + + if *page == self.second + { + second_idx = i; + } + } + + if first_idx > second_idx + { + update.swap(first_idx, second_idx); + } + } +} + + +#[derive(Copy, Clone, PartialEq, Debug)] +enum UpdateStatus +{ + Valid, + Invalid, + Unknown, +} + +#[derive(Clone, Debug)] +struct Update +{ + pages: Vec, + status: UpdateStatus, +} + +impl Update +{ + fn new(pages: Vec) -> Update + { + Update { pages, status: UpdateStatus::Unknown } + } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ead7620..f44db29 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,14 +71,14 @@ fn main() // DAY 5 let mut day_5 = Day5::new(); - day_5.init(DataSet::Test, RunMode::FirstCase, true); + day_5.init(DataSet::Full, RunMode::FirstCase, false); let day5_result = day_5.solve(); println!("Day 5 Part 1 Final Result: {}", day5_result); - // let mut day_5 = Day5::new(); - // day_5.init(DataSet::Test, RunMode::SecondCase, false); - // let day5_result = day_5.solve(); - // println!("Day 5 Part 2 Final Result: {}", day5_result); + let mut day_5 = Day5::new(); + day_5.init(DataSet::Full, RunMode::SecondCase, false); + let day5_result = day_5.solve(); + println!("Day 5 Part 2 Final Result: {}", day5_result); println!("-------------------------");