Skip to content

Commit 961b034

Browse files
committed
[2024] Cleanup day 7
1 parent 918782f commit 961b034

File tree

1 file changed

+31
-70
lines changed

1 file changed

+31
-70
lines changed

aoc_2024/src/day_07.rs

Lines changed: 31 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,27 @@ use common::{solution, Answer};
33
solution!("Bridge Repair", 7);
44

55
fn part_a(input: &str) -> Answer {
6-
let problem = Problem::parse(input);
7-
let mut sum = 0;
8-
9-
for case in problem.cases {
10-
if case.is_valid_a() {
11-
sum += case.result;
12-
}
13-
}
14-
15-
sum.into()
6+
solve(input, false).into()
167
}
178

189
fn part_b(input: &str) -> Answer {
19-
let problem = Problem::parse(input);
20-
let mut sum = 0;
10+
solve(input, true).into()
11+
}
2112

22-
for case in problem.cases {
23-
if case.is_valid_b_working() {
24-
sum += case.result;
25-
}
26-
}
13+
fn solve(input: &str, part_b: bool) -> u64 {
14+
let problem = Problem::parse(input);
2715

28-
sum.into()
16+
// For each of the equations, we will add its result value if it is valid.
17+
// For part a, we check if its valid using `is_valid` with part_b = false,
18+
// because an equation that is valid for part a is must be valid for part b,
19+
// we can get a small speedup by only doing the more intense part_b = true
20+
// check if needed.
21+
problem
22+
.cases
23+
.into_iter()
24+
.filter(|x| x.is_valid(false) || (part_b && x.is_valid(true)))
25+
.map(|x| x.result)
26+
.sum::<u64>()
2927
}
3028

3129
struct Problem {
@@ -66,74 +64,37 @@ impl Problem {
6664
}
6765

6866
impl TestCase {
69-
fn is_valid_a(&self) -> bool {
67+
fn is_valid(&self, part_b: bool) -> bool {
7068
let op_count = self.inputs.len() - 1;
7169
let mut ops = vec![0; op_count];
7270

73-
loop {
71+
'outer: loop {
72+
// Set the result to be the first input value to start. Then update
73+
// the result for each operation using the previous result and the
74+
// next number as inputs.
7475
let mut result = self.inputs[0];
7576
for (&op, &input) in ops.iter().zip(self.inputs.iter().skip(1)) {
7677
let op = [Operations::Add, Operations::Multiply, Operations::Concat][op];
7778
result = op.evaluate(result, input);
7879
}
79-
80-
if result == self.result {
81-
return true;
82-
}
83-
84-
let mut i = 0;
85-
loop {
86-
if i >= op_count {
87-
return false;
88-
}
89-
90-
ops[i] += 1;
91-
if ops[i] > 1 {
92-
ops[i] = 0;
93-
i += 1;
94-
continue;
95-
}
96-
97-
break;
98-
}
99-
}
100-
}
101-
102-
fn is_valid_b_working(&self) -> bool {
103-
let op_count = self.inputs.len() - 1;
104-
let mut ops = vec![0; op_count];
105-
106-
dbg!(&self.inputs);
107-
loop {
108-
let mut result = self.inputs[0];
109-
// println!("{ops:?}");
110-
for (idx, &op) in ops.iter().enumerate() {
111-
let input = self.inputs[idx + 1];
112-
let op = [Operations::Add, Operations::Multiply, Operations::Concat][op];
113-
// println!(" | {op:?} ({result}, {input})");
114-
result = op.evaluate(result, input);
115-
}
11680

81+
// If the result we get after applying the operations gets us the
82+
// expected result, this equation is valid.
11783
if result == self.result {
118-
// println!(" -> WORKS {result}");
11984
return true;
12085
}
12186

122-
let mut i = 0;
123-
loop {
124-
if i >= op_count {
125-
return false;
126-
}
127-
87+
// Increments the leftmost operation, carrying if it exceeds 1 for
88+
// part a or 2 for part b.
89+
for i in 0..op_count {
12890
ops[i] += 1;
129-
if ops[i] > 2 {
130-
ops[i] = 0;
131-
i += 1;
132-
continue;
91+
if ops[i] <= (1 + part_b as usize) {
92+
continue 'outer;
13393
}
134-
135-
break;
94+
ops[i] = 0;
13695
}
96+
97+
return false;
13798
}
13899
}
139100
}

0 commit comments

Comments
 (0)