aoc/year2024/day13.rs
1//! # Claw Contraption
2//!
3//! Each claw machine is a system of two linear equations:
4//!
5//! ```none
6//! (Button A X) * (A presses) + (Button B X) * (B presses) = Prize X
7//! (Button A Y) * (A presses) + (Button B Y) * (B presses) = Prize Y
8//! ```
9//!
10//! Shortening the names and representing as a matrix:
11//!
12//! ```none
13//! [ ax bx ][ a ] = [ px ]
14//! [ ay by ][ b ] = [ py ]
15//! ```
16//!
17//! To solve we invert the 2 x 2 matrix then premultiply the right column.
18use crate::util::iter::*;
19use crate::util::parse::*;
20
21type Claw = [i64; 6];
22
23pub fn parse(input: &str) -> Vec<Claw> {
24 input.iter_signed().chunk::<6>().collect()
25}
26
27pub fn part1(input: &[Claw]) -> i64 {
28 input.iter().map(|row| play(row, false)).sum()
29}
30
31pub fn part2(input: &[Claw]) -> i64 {
32 input.iter().map(|row| play(row, true)).sum()
33}
34
35/// Invert the 2 x 2 matrix representing the system of linear equations.
36fn play(&[ax, ay, bx, by, mut px, mut py]: &Claw, part_two: bool) -> i64 {
37 if part_two {
38 px += 10_000_000_000_000;
39 py += 10_000_000_000_000;
40 }
41
42 // If determinant is zero there's no solution.
43 let det = ax * by - ay * bx;
44 if det == 0 {
45 return 0;
46 }
47
48 let mut a = by * px - bx * py;
49 let mut b = ax * py - ay * px;
50
51 // Integer solutions only.
52 if a % det != 0 || b % det != 0 {
53 return 0;
54 }
55
56 a /= det;
57 b /= det;
58
59 3 * a + b
60}