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