-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib.rs
80 lines (69 loc) · 1.79 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use common::{utils::concat_numbers, Answer};
use itertools::Itertools;
use rayon::prelude::*;
use std::iter::repeat_n;
type IntType = u64;
fn parse(s: &str) -> Vec<(IntType, Vec<IntType>)> {
s.lines()
.map(|l| {
let mut parts = l.split(':');
let result = parts.next().unwrap().parse().unwrap();
let terms = parts
.next()
.unwrap()
.split_whitespace()
.map(|s| s.parse().unwrap())
.collect::<Vec<_>>();
(result, terms)
})
.collect()
}
fn apply(op: &str, a: IntType, b: IntType) -> IntType {
match op {
"add" => a + b,
"mul" => a * b,
"concat" => concat_numbers(a, b),
_ => unreachable!(),
}
}
fn is_solvable(ops: &[&str], result: IntType, terms: &[IntType]) -> bool {
repeat_n(ops.iter(), terms.len() - 1)
.multi_cartesian_product()
.any(|ops| {
terms[1..]
.iter()
.zip(ops)
.fold(terms[0], |acc, (term, op)| apply(op, acc, *term))
== result
})
}
fn sum_solvable(ops: &[&str], s: &str) -> IntType {
parse(s)
.par_iter()
.filter(|(r, t)| is_solvable(ops, *r, t))
.map(|(result, _)| result)
.sum::<IntType>()
}
pub fn step1(s: &str) -> Answer {
sum_solvable(&["add", "mul"], s).into()
}
pub fn step2(s: &str) -> Answer {
sum_solvable(&["add", "mul", "concat"], s).into()
}
#[cfg(test)]
mod test {
use super::*;
const INPUT: &str = 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"#;
#[test]
fn step1_finds_correct_answer() {
assert_eq!(step1(INPUT), Answer::Unsigned(3749));
}
}