Day 7 Complete

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

@ -22,7 +22,7 @@ pub struct Day7
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,
// 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);
}

@ -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<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)]
pub struct Equation
{
values: Vec<i64>,
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<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 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<Operator>) -> 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<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"),
}
}
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