diff --git a/src/solutions/day_06.rs b/src/solutions/day_06.rs index 43c2068..94e3402 100644 --- a/src/solutions/day_06.rs +++ b/src/solutions/day_06.rs @@ -1,3 +1,5 @@ +use itertools::Itertools; + use crate::solution::Solution; #[derive(Clone, Debug)] @@ -17,13 +19,13 @@ impl Problem { #[derive(Debug)] pub struct Day06 { - problems: Vec, + input: String, } -impl Solution for Day06 { - fn with_input(input: String) -> Self { +impl Day06 { + fn parse_input_part1(&self) -> Vec { let mut problem_inputs = Vec::>::new(); - for line in input.lines() { + for line in self.input.lines() { if matches!(line.chars().next().unwrap(), '+' | '*') { let problems = problem_inputs .into_iter() @@ -35,7 +37,7 @@ impl Solution for Day06 { }) .collect(); - return Self { problems }; + return problems; } for (i, n) in line.split_whitespace().enumerate() { @@ -51,8 +53,89 @@ impl Solution for Day06 { panic!("no op line found"); } + fn parse_input_part2(&self) -> Vec { + let lines = self + .input + .lines() + .filter_map(|l| { + if l.is_empty() { + None + } else { + Some(l.bytes().collect_vec()) + } + }) + .collect_vec(); + + let mut problems = Vec::new(); + + let mut current_problem = Vec::new(); + let mut digits = Vec::new(); + let mut current_op = None; + for col in 0..lines[0].len() { + digits.clear(); + digits.extend((0..lines.len() - 1).filter_map(|row| { + let b = lines[row][col]; + if b.is_ascii_digit() { + let d = b - b'0'; + Some(d as u32) + } else { + None + } + })); + + if digits.is_empty() { + let problem = match current_op.take().unwrap() { + b'+' => Problem::Add(current_problem.clone()), + b'*' => Problem::Mul(current_problem.clone()), + _ => panic!(), + }; + problems.push(problem); + current_problem.clear(); + + continue; + } + + let pow = (digits.len() - 1) as u32; + let current_number = digits + .iter() + .copied() + .enumerate() + .map(|(i, d)| 10u32.pow(pow - i as u32) * d) + .sum(); + current_problem.push(current_number); + + let last = lines.last().unwrap()[col]; + if matches!(last, b'+' | b'*') { + current_op = Some(last); + } + } + + let problem = match current_op.unwrap() { + b'+' => Problem::Add(current_problem.clone()), + b'*' => Problem::Mul(current_problem.clone()), + _ => panic!(), + }; + problems.push(problem); + + problems + } +} + +impl Solution for Day06 { + fn with_input(input: String) -> Self { + Self { input } + } + fn part1(&self) -> String { - self.problems + self.parse_input_part1() + .iter() + .map(Problem::eval) + .sum::() + .to_string() + } + + fn part2(&self) -> String { + self.parse_input_part2() .iter() .map(Problem::eval) .sum::()