|
| 1 | +#![allow(non_snake_case)] |
| 2 | + |
| 3 | +use aoc::Puzzle; |
| 4 | + |
| 5 | +#[derive(Debug)] |
| 6 | +struct Machine { |
| 7 | + ax: i64, |
| 8 | + ay: i64, |
| 9 | + bx: i64, |
| 10 | + by: i64, |
| 11 | + px: i64, |
| 12 | + py: i64, |
| 13 | +} |
| 14 | + |
| 15 | +impl Machine { |
| 16 | + fn from_input(block: &[&String]) -> Self { |
| 17 | + let sp: Vec<&str> = block[2].split(", ").collect(); |
| 18 | + Self { |
| 19 | + ax: block[0][12..14].parse::<i64>().unwrap(), |
| 20 | + ay: block[0][18..20].parse::<i64>().unwrap(), |
| 21 | + bx: block[1][12..14].parse::<i64>().unwrap(), |
| 22 | + by: block[1][18..20].parse::<i64>().unwrap(), |
| 23 | + px: sp[0].split_once("=").unwrap().1.parse::<i64>().unwrap(), |
| 24 | + py: sp[1][2..].parse::<i64>().unwrap(), |
| 25 | + } |
| 26 | + } |
| 27 | +} |
| 28 | + |
| 29 | +struct AoC2024_13; |
| 30 | + |
| 31 | +impl AoC2024_13 { |
| 32 | + fn solve(&self, machines: &[Machine], offset: i64) -> u64 { |
| 33 | + fn calc_tokens(machine: &Machine, offset: i64) -> Option<u64> { |
| 34 | + let (px, py) = (machine.px + offset, machine.py + offset); |
| 35 | + let div = |
| 36 | + (machine.bx * machine.ay - machine.ax * machine.by) as f64; |
| 37 | + let ans_a = (py * machine.bx - px * machine.by) as f64 / div; |
| 38 | + let ans_b = (px * machine.ay - py * machine.ax) as f64 / div; |
| 39 | + match ans_a.fract() == 0.0 && ans_b.fract() == 0.0 { |
| 40 | + true => Some(ans_a as u64 * 3 + ans_b as u64), |
| 41 | + false => None, |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + machines.iter().filter_map(|m| calc_tokens(m, offset)).sum() |
| 46 | + } |
| 47 | +} |
| 48 | + |
| 49 | +impl aoc::Puzzle for AoC2024_13 { |
| 50 | + type Input = Vec<Machine>; |
| 51 | + type Output1 = u64; |
| 52 | + type Output2 = u64; |
| 53 | + |
| 54 | + aoc::puzzle_year_day!(2024, 13); |
| 55 | + |
| 56 | + fn parse_input(&self, lines: Vec<String>) -> Self::Input { |
| 57 | + aoc::to_blocks(&lines) |
| 58 | + .iter() |
| 59 | + .map(|block| Machine::from_input(block)) |
| 60 | + .collect() |
| 61 | + } |
| 62 | + |
| 63 | + fn part_1(&self, machines: &Self::Input) -> Self::Output1 { |
| 64 | + self.solve(machines, 0) |
| 65 | + } |
| 66 | + |
| 67 | + fn part_2(&self, machines: &Self::Input) -> Self::Output2 { |
| 68 | + self.solve(machines, 10_000_000_000_000) |
| 69 | + } |
| 70 | + |
| 71 | + fn samples(&self) { |
| 72 | + aoc::puzzle_samples! { |
| 73 | + self, part_1, TEST, 480 |
| 74 | + }; |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +fn main() { |
| 79 | + AoC2024_13 {}.run(std::env::args()); |
| 80 | +} |
| 81 | + |
| 82 | +const TEST: &str = "\ |
| 83 | +Button A: X+94, Y+34 |
| 84 | +Button B: X+22, Y+67 |
| 85 | +Prize: X=8400, Y=5400 |
| 86 | +
|
| 87 | +Button A: X+26, Y+66 |
| 88 | +Button B: X+67, Y+21 |
| 89 | +Prize: X=12748, Y=12176 |
| 90 | +
|
| 91 | +Button A: X+17, Y+86 |
| 92 | +Button B: X+84, Y+37 |
| 93 | +Prize: X=7870, Y=6450 |
| 94 | +
|
| 95 | +Button A: X+69, Y+23 |
| 96 | +Button B: X+27, Y+71 |
| 97 | +Prize: X=18641, Y=10279 |
| 98 | +"; |
| 99 | + |
| 100 | +#[cfg(test)] |
| 101 | +mod tests { |
| 102 | + use super::*; |
| 103 | + |
| 104 | + #[test] |
| 105 | + pub fn samples() { |
| 106 | + AoC2024_13 {}.samples(); |
| 107 | + } |
| 108 | +} |
0 commit comments