Day 7 Complete

master
Joey Pollack 1 year ago
parent 5c4c81ea87
commit 31ea46e466

@ -22,7 +22,7 @@ pub struct Day7
equations: Vec<Equation>, equations: Vec<Equation>,
pub final_result: i32, pub final_result: i64,
} }
//||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@ -47,14 +47,31 @@ impl Day7
{ {
// The engineers just need the total calibration result, // 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. // 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() self.final_result.to_string()
} }
fn solve_second_case(self: &mut Self) -> 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() self.final_result.to_string()
} }
} }
@ -90,12 +107,12 @@ impl Solver for Day7
for line in data.split(split_pattern) 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 // if self.do_debug_prints
{ // {
equation.print(); // equation.print();
} // }
self.equations.push(equation); self.equations.push(equation);
} }

@ -7,25 +7,45 @@
* @brief Represents one calibration equation * @brief Represents one calibration equation
******************************************************************************/ ******************************************************************************/
use std::ops::AddAssign;
#[derive(Copy, Clone, PartialEq, Debug)] #[derive(Copy, Clone, PartialEq, Debug)]
pub enum Operator pub enum Operator
{ {
Add, Add,
Mult, Mult,
Cat,
NumOperators, NumOperators,
} }
impl AddAssign<i32> 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)] #[derive(Clone, Debug)]
pub struct Equation pub struct Equation
{ {
values: Vec<i64>, values: Vec<i64>,
result: i64, result: i64,
enable_debug_prints: bool,
} }
impl Equation impl Equation
{ {
pub fn parse(line: &str) -> Equation pub fn parse(line: &str, enable_debug_prints: bool) -> Equation
{ {
if !line.contains(":") if !line.contains(":")
{ {
@ -48,7 +68,7 @@ impl Equation
} }
Equation { values, result } Equation { values, result, enable_debug_prints }
} }
pub fn print(self: &Equation) pub fn print(self: &Equation)
@ -62,42 +82,156 @@ impl Equation
println!(); println!();
} }
pub fn result(self: &Equation) -> i64
{
self.result
}
// Returns: valid order of operations, or None if the equation can not be valid // 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! // NOTE: Operators are always evaluated left-to-right, not according to precedence rules!
pub fn validate(self: &Equation) -> Option<Vec<Operator>> pub fn validate(self: &Equation, no_concat: bool) -> Option<Vec<Operator>>
{ {
let max_oper =
if no_concat
{
Operator::Mult
}
else
{
Operator::Cat
};
let mut operators = vec![Operator::Add; self.values.len() - 1]; 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() 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)
{ {
operators[i] = match oper_mask & (1 << i) == 0 return Some(operators);
}
let mut i = 0;
while i < operators.len()
{ {
true => Operator::Add, if operators[i] != max_oper
false => Operator::Mult, {
}; operators[i] += 1;
// Reset all previous operators to Add
for (j, oper) in &mut operators.iter_mut().enumerate()
{
if j == i
{
break;
} }
// TODO: Test operator sequence *oper = Operator::Add;
} }
None if self.enable_debug_prints
{
//println!("({}) Trying: {:#?}", permuts_tried + 1, operators);
} }
pub fn oper_sequence_is_valid(self: &Equation, opers: &Vec<Operator>) -> bool permuts_tried += 1;
if self.oper_sequence_is_valid(&operators)
{ {
// let actual_result = 0; return Some(operators);
// for oper in opers }
i = 0;
}
else
{
i += 1;
}
}
if self.enable_debug_prints
{
let num_op_types =
if no_concat
{
Operator::NumOperators as i32 - 1
}
else
{
Operator::NumOperators as i32
};
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
// {
// for i in 0..operators.len()
// { // {
// match oper // operators[i] = match oper_mask & (1 << i) == 0
// { // {
// Operator::Add => // true => Operator::Add,
// false => Operator::Mult,
// };
// } // }
// if self.oper_sequence_is_valid(&operators)
// {
// return Some(operators);
// } // }
// }
None
}
pub fn oper_sequence_is_valid(self: &Equation, opers: &Vec<Operator>) -> 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::<i64>().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"),
}
}
false actual_result == self.result
} }
} }

@ -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.
Loading…
Cancel
Save