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}