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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
use regex::Regex;
#[derive(Debug)]
struct Machine1 {
a: (u32, u32),
b: (u32, u32),
prize: (u32, u32),
}
impl Machine1 {
fn parse(input: &str) -> Vec<Self> {
let mut result: Vec<_> = vec![];
let re = Regex::new(
r"Button A: X\+([0-9]+), Y\+([0-9]+)
Button B: X\+([0-9]+), Y\+([0-9]+)
Prize: X=([0-9]+), Y=([0-9]+)",
)
.unwrap();
for (_, [ax, ay, bx, by, x, y]) in re.captures_iter(input).map(|c| c.extract()) {
result.push(Machine1 {
a: (ax.parse().unwrap(), ay.parse().unwrap()),
b: (bx.parse().unwrap(), by.parse().unwrap()),
prize: (x.parse().unwrap(), y.parse().unwrap()),
});
}
// println!("Result: {result:?}");
result
}
fn solve(&self) -> Option<(u32, u32)> {
for pushesb in (0..100).rev() {
for pushesa in 0..100 {
if self.prize.0 == self.a.0 * pushesa + self.b.0 * pushesb
&& self.prize.1 == self.a.1 * pushesa + self.b.1 * pushesb
{
// println!("{self:?} solved with {pushesa} {pushesb} pushes!");
return Some((pushesa, pushesb));
}
}
}
None
}
}
fn p1(input: &str) -> String {
let result: u32 = Machine1::parse(input)
.iter()
.filter_map(Machine1::solve)
.map(|(nx, ny)| nx * 3 + ny)
.sum();
result.to_string()
}
#[derive(Debug)]
struct Machine2 {
a: (i64, i64),
b: (i64, i64),
prize: (i64, i64),
}
fn intdiv(x: i64, y: i64) -> Option<i64> {
if x % y == 0 {
Some(x / y)
} else {
None
}
}
impl Machine2 {
fn parse(input: &str) -> Vec<Self> {
let mut result: Vec<_> = vec![];
let re = Regex::new(
r"Button A: X\+([0-9]+), Y\+([0-9]+)
Button B: X\+([0-9]+), Y\+([0-9]+)
Prize: X=([0-9]+), Y=([0-9]+)",
)
.unwrap();
for (_, [ax, ay, bx, by, x, y]) in re.captures_iter(input).map(|c| c.extract()) {
result.push(Machine2 {
a: (ax.parse().unwrap(), ay.parse().unwrap()),
b: (bx.parse().unwrap(), by.parse().unwrap()),
prize: (
x.parse::<i64>().unwrap() + 10000000000000,
y.parse::<i64>().unwrap() + 10000000000000,
),
});
}
result
}
fn solve(&self) -> Option<(i64, i64)> {
let pa = intdiv(
self.prize.0 * self.b.1 - self.prize.1 * self.b.0,
self.a.0 * self.b.1 - self.a.1 * self.b.0,
)?;
let pb = intdiv(self.prize.0 - (pa * self.a.0), self.b.0)?;
Some((pa, pb))
}
}
fn p2(input: &str) -> String {
let result: i64 = Machine2::parse(input)
.iter()
.filter_map(Machine2::solve)
.map(|(nx, ny)| nx * 3 + ny)
.sum();
result.to_string()
}
fn main() {
aoc2024::run_day("13", p1, p2);
}
#[cfg(test)]
mod tests {
use super::{p1, p2};
#[test]
fn day13_p1() {
assert_eq!(p1(&aoc2024::read_input("13")), "39290");
}
#[test]
fn day13_p2() {
assert_eq!(p2(&aoc2024::read_input("13")), "73458657399094");
}
}
|