use itertools::{repeat_n, Itertools}; use rayon::prelude::*; use regex::Regex; pub fn day7() { let lines: Vec<(u64, Vec)> = parse_input(&crate::input(7)); let simple_operations = vec![Operation::Add, Operation::Mul]; let simple_operations_total: u64 = lines .par_iter() .filter(|(goal, operands)| possible_totals(operands, &simple_operations).contains(goal)) .map(|(goal, _)| goal) .sum(); let all_operations = vec![Operation::Add, Operation::Mul, Operation::Cat]; let all_operations_total: u64 = lines .par_iter() .filter(|(goal, operands)| possible_totals(operands, &all_operations).contains(goal)) .map(|(goal, _)| goal) .sum(); println!("Total for +/*: {}", simple_operations_total); println!("Total for All: {}", all_operations_total); } fn possible_totals(operands: &Vec, operations: &Vec) -> Vec { repeat_n(operations, operands.len() - 1) .multi_cartesian_product() .map(|operations| { operands[1..] .iter() .zip(operations) .fold(operands[0], |acc, (e, op)| op.apply(acc, *e)) }) .collect() } fn parse_input(input: &str) -> Vec<(u64, Vec)> { input .lines() .map(|line| { let all: Vec = Regex::new(r"\D+") .unwrap() .split(line) .map(|s| s.parse().unwrap()) .collect(); (all[0], all[1..].to_vec()) }) .collect() } #[derive(Clone)] enum Operation { Add, Mul, Cat, } impl Operation { fn apply(&self, a: u64, b: u64) -> u64 { match self { Self::Add => a + b, Self::Mul => a * b, Self::Cat => (a.to_string() + &b.to_string()).parse().unwrap(), } } }