#[path = "../lib.rs"] mod lib; fn part1(ax: i64, ay: i64, bx: i64, by: i64, cx: i64, cy: i64) -> i64 { // a * ax + b * bx = cx // a * ay + b * by = cy // solve for a and b after eleminating the other: // a = (cx * by - cy * bx) / (ax * by - ay * bx) // b = (cy * ax - cx * ay) / (ax * by - ay * bx) let v = ax * by - ay * bx; let va = cx * by - cy * bx; let vb = cy * ax - cx * ay; if v == 0 { // a and b are linear dependent // doesn't happen in the puzzle data unreachable!(); } else if va % v == 0 && vb % v == 0 { // there is only one unique solution // the "find the cheapest option" is a red herring let a = va / v; let b = vb / v; return a * 3 + b; } else { // there is no solution return 0; } } fn main() { let mut sum1 = 0; let mut sum2 = 0; let mut ax = 0; let mut ay = 0; let mut bx = 0; let mut by = 0; for line in lib::iter_input() { if let Some((label, values)) = line.split_once(": ") { let (sx, sy) = values.split_once(", ").unwrap(); let vx = sx[2..].parse::().unwrap(); let vy = sy[2..].parse::().unwrap(); match label { "Button A" => { ax = vx; ay = vy; }, "Button B" => { bx = vx; by = vy; }, "Prize" => { sum1 += part1(ax, ay, bx, by, vx, vy); sum2 += part1(ax, ay, bx, by, 10_000_000_000_000 + vx, 10_000_000_000_000 + vy); }, _ => unreachable!(), }; } } println!("part1: {}", sum1); println!("part2: {}", sum2); }