|
|
|
|
@ -19,6 +19,7 @@ pub struct Day5
|
|
|
|
|
pub final_result: i32,
|
|
|
|
|
|
|
|
|
|
rules: Vec<Rule>,
|
|
|
|
|
updates: Vec<Update>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
@ -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<i32> = vec![];
|
|
|
|
|
for page in row.split(",")
|
|
|
|
|
{
|
|
|
|
|
let page_i = page.parse::<i32>().expect(&format!("ERROR: Failed to parse update page: {}", page));
|
|
|
|
|
pages.push(page_i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.updates.push(Update::new(pages));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -92,9 +175,22 @@ 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!();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -120,6 +216,30 @@ impl Solver for Day5
|
|
|
|
|
// EXTRA STUFF
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
fn check_updates(updates: &mut Vec<Update>, rules: &Vec<Rule>, 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<i32>, 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<i32>, 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<i32>,
|
|
|
|
|
status: UpdateStatus,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Update
|
|
|
|
|
{
|
|
|
|
|
fn new(pages: Vec<i32>) -> Update
|
|
|
|
|
{
|
|
|
|
|
Update { pages, status: UpdateStatus::Unknown }
|
|
|
|
|
}
|
|
|
|
|
}
|