diff --git a/src/main.rs b/src/main.rs index 852da79..535bbc3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,7 @@ fn main() -> Result<()> { 4 => AocDayFourSolution, 5 => AocDayFiveSolution, 6 => AocDaySixSolution, + 7 => AocDaySevenSolution, }; Ok(()) diff --git a/src/solutions/day_7.rs b/src/solutions/day_7.rs index dc523c1..e98311d 100644 --- a/src/solutions/day_7.rs +++ b/src/solutions/day_7.rs @@ -1,8 +1,109 @@ -use std::{fs::read_to_string, path::Path}; +use std::{fs::read_to_string, ops::Mul, path::Path}; use super::AocSolution; use crate::utils::Result; +fn compute(nums: &[u64], total: u64) -> bool { + let mut equations = vec![false; nums.len() - 1]; + + fn _inc_xf(flags: &mut [bool]) { + let mut carry = true; + for flag in flags.iter_mut().rev() { + if !carry { + break; + } + + let tmp = *flag; + *flag = !tmp; + carry = tmp; + } + } + + loop { + if equations.iter().zip(1..).fold( + nums[0], + |n, (&x, idx)| { + if x { + n * nums[idx] + } else { + n + nums[idx] + } + }, + ) == total + { + return true; + } else { + if equations.iter().all(|b| *b) { + break; + } + _inc_xf(&mut equations); + } + } + + false +} + +fn concat(n1: u64, n2: u64) -> u64 { + format!("{n1}{n2}").parse().unwrap() +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Operation { + Add, + Mul, + Concat, +} + +impl Operation { + fn inc(self) -> Self { + match self { + Self::Add => Self::Mul, + Self::Mul => Self::Concat, + Self::Concat => Self::Add, + } + } +} + +fn compute_ver_two(nums: &[u64], total: u64) -> bool { + let mut equations = vec![Operation::Add; nums.len() - 1]; + + fn _inc_xf(flags: &mut [Operation]) { + let mut carry = true; + for flag in flags.iter_mut().rev() { + if !carry { + break; + } + + let tmp = *flag; + *flag = tmp.inc(); + carry = tmp == Operation::Concat; + } + } + + loop { + if equations + .iter() + .zip(1..) + .fold(nums[0], |n, (&x, idx)| match x { + Operation::Add => n + nums[idx], + Operation::Mul => n * nums[idx], + Operation::Concat => concat(n, nums[idx]), + }) + == total + { + return true; + } else { + if equations.iter().all(|b| *b == Operation::Concat) { + break; + } + _inc_xf(&mut equations); + } + } + + false +} + +#[derive(Clone, Copy)] pub struct AocDaySevenSolution; impl AocSolution for AocDaySevenSolution { @@ -11,15 +112,66 @@ impl AocSolution for AocDaySevenSolution { fn get_input(&self, path: Option<&Path>) -> Result { Ok(match path { Some(p) => read_to_string(p)?, - None => read_to_string("./input/day_day_7.txt")?, + None => read_to_string("./input/day_7.txt")?, }) } fn part_one(&self, input: &str) -> Result { - todo!() + let mut sum = 0; + for line in input.lines() { + if let Some((total, nums)) = line.split_once(':') { + let total = total.parse::()?; + let nums = nums + .split_whitespace() + .map(|n| n.parse::().map_err(|e| e.into())) + .collect::>>()?; + + if compute(&nums, total) { + sum += total; + } + } + } + + Ok(sum) } fn part_two(&self, input: &str) -> Result { - todo!() + let mut sum = 0; + for line in input.lines() { + if let Some((total, nums)) = line.split_once(':') { + let total = total.parse::()?; + let nums = nums + .split_whitespace() + .map(|n| n.parse::().map_err(|e| e.into())) + .collect::>>()?; + + if compute_ver_two(&nums, total) { + sum += total; + } + } + } + + Ok(sum) } } + +#[test] +fn test() { + let sol = AocDaySevenSolution; + + assert_eq!( + sol.part_one( + r#"190: 10 19 +3267: 81 40 27 +83: 17 5 +156: 15 6 +7290: 6 8 6 15 +161011: 16 10 13 +192: 17 8 14 +21037: 9 7 18 13 +292: 11 6 16 20"# + ) + .unwrap(), + 3749 + ); +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d95b8aa..287db50 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -8,6 +8,8 @@ pub type Result = std::result::Result; #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("Error parsing integer: {0}")] + ParseNumErr(#[from] std::num::ParseIntError), #[error("IO error: {0}")] Io(#[from] std::io::Error), #[error("Invalid command usage: {0}")]