use regex::Regex; #[derive(Debug)] struct Machine1 { a: (u32, u32), b: (u32, u32), prize: (u32, u32), } impl Machine1 { fn parse(input: &str) -> Vec { let mut result: Vec<_> = vec![]; let re = Regex::new( r"Button A: X\+([0-9]+), Y\+([0-9]+) Button B: X\+([0-9]+), Y\+([0-9]+) Prize: X=([0-9]+), Y=([0-9]+)", ) .unwrap(); for (_, [ax, ay, bx, by, x, y]) in re.captures_iter(input).map(|c| c.extract()) { result.push(Machine1 { a: (ax.parse().unwrap(), ay.parse().unwrap()), b: (bx.parse().unwrap(), by.parse().unwrap()), prize: (x.parse().unwrap(), y.parse().unwrap()), }); } // println!("Result: {result:?}"); result } fn solve(&self) -> Option<(u32, u32)> { for pushesb in (0..100).rev() { for pushesa in 0..100 { if self.prize.0 == self.a.0 * pushesa + self.b.0 * pushesb && self.prize.1 == self.a.1 * pushesa + self.b.1 * pushesb { // println!("{self:?} solved with {pushesa} {pushesb} pushes!"); return Some((pushesa, pushesb)); } } } None } } fn p1(input: &str) -> String { let result: u32 = Machine1::parse(input) .iter() .filter_map(Machine1::solve) .map(|(nx, ny)| nx * 3 + ny) .sum(); result.to_string() } #[derive(Debug)] struct Machine2 { a: (i64, i64), b: (i64, i64), prize: (i64, i64), } fn intdiv(x: i64, y: i64) -> Option { if x % y == 0 { Some(x / y) } else { None } } impl Machine2 { fn parse(input: &str) -> Vec { let mut result: Vec<_> = vec![]; let re = Regex::new( r"Button A: X\+([0-9]+), Y\+([0-9]+) Button B: X\+([0-9]+), Y\+([0-9]+) Prize: X=([0-9]+), Y=([0-9]+)", ) .unwrap(); for (_, [ax, ay, bx, by, x, y]) in re.captures_iter(input).map(|c| c.extract()) { result.push(Machine2 { a: (ax.parse().unwrap(), ay.parse().unwrap()), b: (bx.parse().unwrap(), by.parse().unwrap()), prize: ( x.parse::().unwrap() + 10000000000000, y.parse::().unwrap() + 10000000000000, ), }); } result } fn solve(&self) -> Option<(i64, i64)> { let pa = intdiv( self.prize.0 * self.b.1 - self.prize.1 * self.b.0, self.a.0 * self.b.1 - self.a.1 * self.b.0, )?; let pb = intdiv(self.prize.0 - (pa * self.a.0), self.b.0)?; Some((pa, pb)) } } fn p2(input: &str) -> String { let result: i64 = Machine2::parse(input) .iter() .filter_map(Machine2::solve) .map(|(nx, ny)| nx * 3 + ny) .sum(); result.to_string() } fn main() { aoc2024::run_day("13", p1, p2); } #[cfg(test)] mod tests { use super::{p1, p2}; #[test] fn day13_p1() { assert_eq!(p1(&aoc2024::read_input("13")), "39290"); } #[test] fn day13_p2() { assert_eq!(p2(&aoc2024::read_input("13")), "73458657399094"); } }