Skip to content

Commit 1b38af8

Browse files
committed
Day 7
1 parent 22080e4 commit 1b38af8

File tree

4 files changed

+138
-0
lines changed

4 files changed

+138
-0
lines changed

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ today = ["chrono"]
2020
test_lib = []
2121

2222
[dependencies]
23+
bit-set = "0.8.0"
2324

2425
# Template dependencies
2526
chrono = { version = "0.4.38", optional = true }

data/examples/07.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
190: 10 19
2+
3267: 81 40 27
3+
83: 17 5
4+
156: 15 6
5+
7290: 6 8 6 15
6+
161011: 16 10 13
7+
192: 17 8 14
8+
21037: 9 7 18 13
9+
292: 11 6 16 20

src/bin/07.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
advent_of_code::solution!(7);
2+
use itertools::Itertools;
3+
4+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5+
enum Op {
6+
Add,
7+
Mul,
8+
Concat,
9+
}
10+
11+
type OpVec = Vec<Op>;
12+
#[derive(Debug)]
13+
struct EquationData {
14+
test_value: u64,
15+
values: Vec<u64>,
16+
}
17+
18+
impl EquationData {
19+
fn parse(line: &str) -> Self {
20+
let (left, right) = line.split_once(": ").unwrap();
21+
let test_value = left.parse().unwrap();
22+
let values = right.split(" ").map(|s| s.parse().unwrap()).collect();
23+
Self { test_value, values }
24+
}
25+
26+
fn eval(&self, ops: &OpVec) -> u64 {
27+
let mut res = 0;
28+
let mut op = Op::Add;
29+
for i in 0..self.values.len() {
30+
let v = self.values[i];
31+
res = match op {
32+
Op::Add => res + v,
33+
Op::Mul => res * v,
34+
Op::Concat => {
35+
let char_count = v.to_string().len() as u32;
36+
res * 10_u64.pow(char_count) + v
37+
}
38+
};
39+
if i < ops.len() {
40+
op = ops[i];
41+
}
42+
}
43+
res
44+
}
45+
}
46+
47+
pub fn part_one(input: &str) -> Option<u64> {
48+
const ALL_OPS: [Op; 2] = [Op::Add, Op::Mul];
49+
let sum = input
50+
.lines()
51+
.filter(|l| !l.is_empty())
52+
.map(|l| EquationData::parse(l))
53+
.filter(|eq| {
54+
for ops in std::iter::repeat_n(ALL_OPS, eq.values.len() - 1).multi_cartesian_product() {
55+
if eq.eval(&ops) == eq.test_value {
56+
return true;
57+
}
58+
}
59+
false
60+
})
61+
.map(|eq| eq.test_value)
62+
.sum();
63+
Some(sum)
64+
}
65+
66+
pub fn part_two(input: &str) -> Option<u64> {
67+
const ALL_OPS: [Op; 3] = [Op::Add, Op::Mul, Op::Concat];
68+
let sum = input
69+
.lines()
70+
.filter(|l| !l.is_empty())
71+
.map(|l| EquationData::parse(l))
72+
.filter(|eq| {
73+
for ops in std::iter::repeat_n(ALL_OPS, eq.values.len() - 1).multi_cartesian_product() {
74+
if eq.eval(&ops) == eq.test_value {
75+
return true;
76+
}
77+
}
78+
false
79+
})
80+
.map(|eq| eq.test_value)
81+
.sum();
82+
Some(sum)
83+
}
84+
85+
#[cfg(test)]
86+
mod tests {
87+
use super::*;
88+
89+
#[test]
90+
fn test_eval() {
91+
let eq = EquationData {
92+
test_value: 10,
93+
values: vec![1, 2, 3],
94+
};
95+
assert_eq!(eq.eval(&vec![Op::Add, Op::Add]), 6);
96+
assert_eq!(eq.eval(&vec![Op::Add, Op::Mul]), 9);
97+
assert_eq!(eq.eval(&vec![Op::Mul, Op::Add]), 5);
98+
assert_eq!(eq.eval(&vec![Op::Mul, Op::Mul]), 6);
99+
}
100+
101+
#[test]
102+
fn test_part_one() {
103+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
104+
assert_eq!(result, Some(3749));
105+
}
106+
107+
#[test]
108+
fn test_part_two() {
109+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
110+
assert_eq!(result, Some(11387));
111+
}
112+
}

0 commit comments

Comments
 (0)