From 31ea46e466a4100fd4ae29ea5678652f1a467f45 Mon Sep 17 00:00:00 2001 From: Joey Pollack Date: Thu, 12 Dec 2024 01:35:50 -0500 Subject: [PATCH] Day 7 Complete --- crates/day_7/src/day_7.rs | 33 +++++-- crates/day_7/src/equation.rs | 176 ++++++++++++++++++++++++++++++----- scratch | 45 +++++++++ 3 files changed, 225 insertions(+), 29 deletions(-) create mode 100644 scratch diff --git a/crates/day_7/src/day_7.rs b/crates/day_7/src/day_7.rs index ab47321..54e66d5 100644 --- a/crates/day_7/src/day_7.rs +++ b/crates/day_7/src/day_7.rs @@ -22,7 +22,7 @@ pub struct Day7 equations: Vec, - pub final_result: i32, + pub final_result: i64, } //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| @@ -47,14 +47,31 @@ impl Day7 { // The engineers just need the total calibration result, // which is the sum of the test values from just the equations that could possibly be true. - + let mut sum = 0; + for e in &self.equations + { + if let Some(_) = e.validate(true) + { + sum += e.result(); + } + } + + self.final_result = sum; self.final_result.to_string() } fn solve_second_case(self: &mut Self) -> String { + let mut sum = 0; + for e in &self.equations + { + if let Some(_) = e.validate(false) + { + sum += e.result(); + } + } - + self.final_result = sum; self.final_result.to_string() } } @@ -90,12 +107,12 @@ impl Solver for Day7 for line in data.split(split_pattern) { - let equation = Equation::parse(line); + let equation = Equation::parse(line, self.do_debug_prints); - if self.do_debug_prints - { - equation.print(); - } + // if self.do_debug_prints + // { + // equation.print(); + // } self.equations.push(equation); } diff --git a/crates/day_7/src/equation.rs b/crates/day_7/src/equation.rs index bf867dd..660e882 100644 --- a/crates/day_7/src/equation.rs +++ b/crates/day_7/src/equation.rs @@ -7,25 +7,45 @@ * @brief Represents one calibration equation ******************************************************************************/ +use std::ops::AddAssign; + #[derive(Copy, Clone, PartialEq, Debug)] pub enum Operator { Add, Mult, + Cat, NumOperators, } +impl AddAssign for Operator +{ + fn add_assign(&mut self, rhs: i32) + { + *self = match (*self as i32 + rhs) % (Operator::NumOperators as i32) + { + 0 => Operator::Add, + 1 => Operator::Mult, + 2 => Operator::Cat, + + _ => panic!("Yo wtf?"), + } + } +} + #[derive(Clone, Debug)] pub struct Equation { values: Vec, result: i64, + + enable_debug_prints: bool, } impl Equation { - pub fn parse(line: &str) -> Equation + pub fn parse(line: &str, enable_debug_prints: bool) -> Equation { if !line.contains(":") { @@ -48,7 +68,7 @@ impl Equation } - Equation { values, result } + Equation { values, result, enable_debug_prints } } pub fn print(self: &Equation) @@ -62,42 +82,156 @@ impl Equation println!(); } + pub fn result(self: &Equation) -> i64 + { + self.result + } + // Returns: valid order of operations, or None if the equation can not be valid // NOTE: Operators are always evaluated left-to-right, not according to precedence rules! - pub fn validate(self: &Equation) -> Option> + pub fn validate(self: &Equation, no_concat: bool) -> Option> { + let max_oper = + if no_concat + { + Operator::Mult + } + else + { + Operator::Cat + }; + let mut operators = vec![Operator::Add; self.values.len() - 1]; - let num_oper_permutations = (Operator::NumOperators as i32).pow(operators.len() as u32); - for oper_mask in 0..num_oper_permutations + if self.enable_debug_prints { - for i in 0..operators.len() - { - operators[i] = match oper_mask & (1 << i) == 0 + self.print(); + } + + + // Iterate all set permutations: + // iterate up to the first not max-value digit, + // increase it, + // if it is now max-value + // then reset all previous digits to the lowest value. + // if all digits are max-value + // then break + + let mut permuts_tried = 0; + + permuts_tried += 1; + if self.oper_sequence_is_valid(&operators) + { + return Some(operators); + } + + let mut i = 0; + while i < operators.len() + { + if operators[i] != max_oper + { + operators[i] += 1; + + // Reset all previous operators to Add + for (j, oper) in &mut operators.iter_mut().enumerate() { - true => Operator::Add, - false => Operator::Mult, - }; + if j == i + { + break; + } + + *oper = Operator::Add; + } + + if self.enable_debug_prints + { + //println!("({}) Trying: {:#?}", permuts_tried + 1, operators); + } + + permuts_tried += 1; + if self.oper_sequence_is_valid(&operators) + { + return Some(operators); + } + + i = 0; + } + else + { + i += 1; } - // TODO: Test operator sequence } - None - } + if self.enable_debug_prints + { + let num_op_types = + if no_concat + { + Operator::NumOperators as i32 - 1 + } + else + { + Operator::NumOperators as i32 + }; - pub fn oper_sequence_is_valid(self: &Equation, opers: &Vec) -> bool - { - // let actual_result = 0; - // for oper in opers + println!("Invalid! Num Opers: {}, Num Oper Types: {}, Num permutations tried: {}", + operators.len(), num_op_types, permuts_tried); + } + + + + // Note: The old, 2-oper version + // let num_oper_permutations = num_opers.pow(operators.len() as u32); + // for oper_mask in 0..num_oper_permutations // { - // match oper + // for i in 0..operators.len() // { - // Operator::Add => + // operators[i] = match oper_mask & (1 << i) == 0 + // { + // true => Operator::Add, + // false => Operator::Mult, + // }; + // } + + // if self.oper_sequence_is_valid(&operators) + // { + // return Some(operators); // } // } - false + None + } + + pub fn oper_sequence_is_valid(self: &Equation, opers: &Vec) -> bool + { + let mut values_clone = self.values.clone(); + let mut actual_result = self.values[0]; + + let mut print_test_cat = self.enable_debug_prints; + + for (i, oper) in opers.iter().enumerate() + { + match oper + { + Operator::Add => actual_result = actual_result + values_clone[i + 1], + Operator::Mult => actual_result = actual_result * values_clone[i + 1], + Operator::Cat => + { + let cat = (actual_result.to_string() + &values_clone[i + 1].to_string()).parse::().unwrap(); + if print_test_cat + { + //println!("Test Cat: {} || {} = {}", actual_result, values_clone[i + 1], cat); + print_test_cat = false; + } + + actual_result = cat; + }, + Operator::NumOperators => panic!("ERROR: Invalid operator sequence: Operator::NumOperators found"), + } + } + + actual_result == self.result } } \ No newline at end of file diff --git a/scratch b/scratch new file mode 100644 index 0000000..71341fd --- /dev/null +++ b/scratch @@ -0,0 +1,45 @@ +000 - +001 +002 +010 - +011 +012 +020 - +021 +022 +100 - +101 +102 +110 - +111 +112 +120 - +121 +122 +200 - +201 +202 +210- +211 +212 +220- +221 +222 + + +000 +001 +010 +011 +100 +101 +110 +111 + + + + +move left to right up to the first not max-value digit, +increase it, +if it is now max-value +then reset all previous digits to the lowest value.