e84087dec40d1f7281f2d59c90301b697b2d0ca2
[advent_of_code_2024.git] / src / day13.rs
1 use std::io::BufRead;
2
3 use nalgebra::{stack, Vector2};
4 use regex::Regex;
5
6 type Equations = Vec<(Vector2<i64>, Vector2<i64>, Vector2<i64>)>;
7
8 pub fn read(reader: &mut dyn BufRead) -> Equations {
9 let button_a = Regex::new(r#"Button A: X\+(\d+), Y\+(\d+)"#).unwrap();
10 let button_b = Regex::new(r#"Button B: X\+(\d+), Y\+(\d+)"#).unwrap();
11 let prize = Regex::new(r#"Prize: X=(\d+), Y=(\d+)"#).unwrap();
12
13 let mut equations = Vec::new();
14 let mut iter = reader.lines();
15 loop {
16 if let Some(Ok(line1)) = iter.next() {
17 let a_cap = button_a.captures(&line1).unwrap();
18 let a_factors = Vector2::new(
19 a_cap[1].parse::<i64>().unwrap(),
20 a_cap[2].parse::<i64>().unwrap(),
21 );
22 let line2 = iter.next().unwrap().unwrap();
23 let b_cap = button_b.captures(&line2).unwrap();
24 let b_factors = Vector2::new(
25 b_cap[1].parse::<i64>().unwrap(),
26 b_cap[2].parse::<i64>().unwrap(),
27 );
28 let line3 = iter.next().unwrap().unwrap();
29 let prize_cap = prize.captures(&line3).unwrap();
30 let prize_xy = Vector2::new(
31 prize_cap[1].parse::<i64>().unwrap(),
32 prize_cap[2].parse::<i64>().unwrap(),
33 );
34 let _ = iter.next();
35 equations.push((a_factors, b_factors, prize_xy));
36 } else {
37 break;
38 }
39 }
40 equations
41 }
42
43 pub fn add_10000000000000_to_xy(equations: Equations) -> Equations {
44 equations
45 .into_iter()
46 .map(|(a_v, b_v, xy)| (a_v, b_v, xy.add_scalar(10000000000000)))
47 .collect()
48 }
49
50 pub fn nb_tokens(equations: &Equations) -> i64 {
51 equations
52 .iter()
53 .filter_map(|(a_v, b_v, xy)| {
54 let d = stack![a_v.cast::<f64>(), b_v.cast::<f64>()].determinant();
55 if d == 0f64 {
56 return None;
57 }
58 let a = (stack![xy.cast::<f64>(), b_v.cast::<f64>()].determinant() / d) as i64;
59 let b = (stack![a_v.cast::<f64>(), xy.cast::<f64>()].determinant() / d) as i64;
60
61 if a * a_v[0] + b * b_v[0] == xy[0] && a * a_v[1] + b * b_v[1] == xy[1] {
62 Some(3 * a + b)
63 } else {
64 None
65 }
66 })
67 .sum()
68 }
69
70 #[cfg(test)]
71 mod tests {
72 use super::*;
73
74 static BUTTON_BEHAVIORS: &str = "Button A: X+94, Y+34
75 Button B: X+22, Y+67
76 Prize: X=8400, Y=5400
77
78 Button A: X+26, Y+66
79 Button B: X+67, Y+21
80 Prize: X=12748, Y=12176
81
82 Button A: X+17, Y+86
83 Button B: X+84, Y+37
84 Prize: X=7870, Y=6450
85
86 Button A: X+69, Y+23
87 Button B: X+27, Y+71
88 Prize: X=18641, Y=10279";
89
90 #[test]
91 fn part1() {
92 let equations = read(&mut BUTTON_BEHAVIORS.as_bytes());
93 assert_eq!(nb_tokens(&equations), 480);
94 }
95 }