68 lines
1.8 KiB
Rust
68 lines
1.8 KiB
Rust
use itertools::{repeat_n, Itertools};
|
|
use rayon::prelude::*;
|
|
use regex::Regex;
|
|
|
|
pub fn day7() {
|
|
let lines: Vec<(u64, Vec<u64>)> = 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<u64>, operations: &Vec<Operation>) -> Vec<u64> {
|
|
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<u64>)> {
|
|
input
|
|
.lines()
|
|
.map(|line| {
|
|
let all: Vec<u64> = 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(),
|
|
}
|
|
}
|
|
}
|