--- /dev/null
+use std::io::BufRead;
+
+use nalgebra::{stack, Vector2};
+use regex::Regex;
+
+type Equations = Vec<(Vector2<i64>, Vector2<i64>, Vector2<i64>)>;
+
+pub fn read(reader: &mut dyn BufRead) -> Equations {
+ let button_a = Regex::new(r#"Button A: X\+(\d+), Y\+(\d+)"#).unwrap();
+ let button_b = Regex::new(r#"Button B: X\+(\d+), Y\+(\d+)"#).unwrap();
+ let prize = Regex::new(r#"Prize: X=(\d+), Y=(\d+)"#).unwrap();
+
+ let mut equations = Vec::new();
+ let mut iter = reader.lines();
+ loop {
+ if let Some(Ok(line1)) = iter.next() {
+ let a_cap = button_a.captures(&line1).unwrap();
+ let a_factors = Vector2::new(
+ a_cap.get(1).unwrap().as_str().parse::<i64>().unwrap(),
+ a_cap.get(2).unwrap().as_str().parse::<i64>().unwrap(),
+ );
+ let line2 = iter.next().unwrap().unwrap();
+ let b_cap = button_b.captures(&line2).unwrap();
+ let b_factors = Vector2::new(
+ b_cap.get(1).unwrap().as_str().parse::<i64>().unwrap(),
+ b_cap.get(2).unwrap().as_str().parse::<i64>().unwrap(),
+ );
+ let line3 = iter.next().unwrap().unwrap();
+ let prize_cap = prize.captures(&line3).unwrap();
+ let prize_xy = Vector2::new(
+ prize_cap.get(1).unwrap().as_str().parse::<i64>().unwrap(),
+ prize_cap.get(2).unwrap().as_str().parse::<i64>().unwrap(),
+ );
+ let _ = iter.next();
+ equations.push((a_factors, b_factors, prize_xy));
+ } else {
+ break;
+ }
+ }
+ equations
+}
+
+pub fn add_10000000000000_to_xy(equations: Equations) -> Equations {
+ equations
+ .into_iter()
+ .map(|(a_v, b_v, xy)| (a_v, b_v, xy.add_scalar(10000000000000)))
+ .collect()
+}
+
+pub fn nb_tokens(equations: &Equations) -> i64 {
+ equations
+ .iter()
+ .filter_map(|(a_v, b_v, xy)| {
+ let d = stack![a_v.cast::<f64>(), b_v.cast::<f64>()].determinant();
+ if d == 0f64 {
+ return None;
+ }
+ let a = (stack![xy.cast::<f64>(), b_v.cast::<f64>()].determinant() / d) as i64;
+ let b = (stack![a_v.cast::<f64>(), xy.cast::<f64>()].determinant() / d) as i64;
+
+ if a * a_v[0] + b * b_v[0] == xy[0] && a * a_v[1] + b * b_v[1] == xy[1] {
+ Some(3 * a + b)
+ } else {
+ None
+ }
+ })
+ .sum()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ static BUTTON_BEHAVIORS: &str = "Button A: X+94, Y+34
+Button B: X+22, Y+67
+Prize: X=8400, Y=5400
+
+Button A: X+26, Y+66
+Button B: X+67, Y+21
+Prize: X=12748, Y=12176
+
+Button A: X+17, Y+86
+Button B: X+84, Y+37
+Prize: X=7870, Y=6450
+
+Button A: X+69, Y+23
+Button B: X+27, Y+71
+Prize: X=18641, Y=10279";
+
+ #[test]
+ fn part1() {
+ let equations = read(&mut BUTTON_BEHAVIORS.as_bytes());
+ assert_eq!(nb_tokens(&equations), 480);
+ }
+}