Skip to content

Commit 918782f

Browse files
committed
[2024] Day 7 initial solution
1 parent 571b776 commit 918782f

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

aoc_2024/src/day_07.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
use common::{solution, Answer};
2+
3+
solution!("Bridge Repair", 7);
4+
5+
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()
16+
}
17+
18+
fn part_b(input: &str) -> Answer {
19+
let problem = Problem::parse(input);
20+
let mut sum = 0;
21+
22+
for case in problem.cases {
23+
if case.is_valid_b_working() {
24+
sum += case.result;
25+
}
26+
}
27+
28+
sum.into()
29+
}
30+
31+
struct Problem {
32+
cases: Vec<TestCase>,
33+
}
34+
35+
struct TestCase {
36+
result: u64,
37+
inputs: Vec<u64>,
38+
}
39+
40+
#[derive(Clone, Copy, Debug)]
41+
enum Operations {
42+
Add,
43+
Multiply,
44+
Concat,
45+
}
46+
47+
impl Problem {
48+
fn parse(input: &str) -> Self {
49+
let cases = input
50+
.lines()
51+
.map(|x| {
52+
let (result, inputs) = x.split_once(": ").unwrap();
53+
54+
let result = result.parse::<u64>().unwrap();
55+
let inputs = inputs
56+
.split_whitespace()
57+
.map(|x| x.parse::<u64>().unwrap())
58+
.collect::<Vec<_>>();
59+
60+
TestCase { result, inputs }
61+
})
62+
.collect::<Vec<_>>();
63+
64+
Self { cases }
65+
}
66+
}
67+
68+
impl TestCase {
69+
fn is_valid_a(&self) -> bool {
70+
let op_count = self.inputs.len() - 1;
71+
let mut ops = vec![0; op_count];
72+
73+
loop {
74+
let mut result = self.inputs[0];
75+
for (&op, &input) in ops.iter().zip(self.inputs.iter().skip(1)) {
76+
let op = [Operations::Add, Operations::Multiply, Operations::Concat][op];
77+
result = op.evaluate(result, input);
78+
}
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+
}
116+
117+
if result == self.result {
118+
// println!(" -> WORKS {result}");
119+
return true;
120+
}
121+
122+
let mut i = 0;
123+
loop {
124+
if i >= op_count {
125+
return false;
126+
}
127+
128+
ops[i] += 1;
129+
if ops[i] > 2 {
130+
ops[i] = 0;
131+
i += 1;
132+
continue;
133+
}
134+
135+
break;
136+
}
137+
}
138+
}
139+
}
140+
141+
impl Operations {
142+
fn evaluate(&self, a: u64, b: u64) -> u64 {
143+
match self {
144+
Operations::Add => a + b,
145+
Operations::Multiply => a * b,
146+
Operations::Concat => {
147+
let mut out = a;
148+
let mut tmp = b;
149+
while tmp > 0 {
150+
tmp /= 10;
151+
out *= 10;
152+
}
153+
out + b
154+
}
155+
}
156+
}
157+
}
158+
159+
#[cfg(test)]
160+
mod test {
161+
use indoc::indoc;
162+
163+
const CASE: &str = indoc! {"
164+
190: 10 19
165+
3267: 81 40 27
166+
83: 17 5
167+
156: 15 6
168+
7290: 6 8 6 15
169+
161011: 16 10 13
170+
192: 17 8 14
171+
21037: 9 7 18 13
172+
292: 11 6 16 20
173+
"};
174+
175+
#[test]
176+
fn part_a() {
177+
assert_eq!(super::part_a(CASE), 3749.into());
178+
}
179+
180+
#[test]
181+
fn part_b() {
182+
assert_eq!(super::part_b(CASE), 11387.into());
183+
}
184+
}

aoc_2024/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod day_03;
66
mod day_04;
77
mod day_05;
88
mod day_06;
9+
mod day_07;
910
// [import_marker]
1011

1112
pub const SOLUTIONS: &[Solution] = &[
@@ -15,5 +16,6 @@ pub const SOLUTIONS: &[Solution] = &[
1516
day_04::SOLUTION,
1617
day_05::SOLUTION,
1718
day_06::SOLUTION,
19+
day_07::SOLUTION,
1820
// [list_marker]
1921
];

0 commit comments

Comments
 (0)