Skip to content

Commit

Permalink
improve code for day13
Browse files Browse the repository at this point in the history
  • Loading branch information
mirsella committed Dec 13, 2024
1 parent 03367fc commit 944efe9
Showing 1 changed file with 50 additions and 54 deletions.
104 changes: 50 additions & 54 deletions 2024/day13/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use regex::Regex;

#[derive(Debug)]
struct Machine {
pub a: (usize, usize),
pub b: (usize, usize),
pub prize: (usize, usize),
pub a: (i64, i64),
pub b: (i64, i64),
pub prize: (i64, i64),
}

impl Machine {
Expand All @@ -27,28 +27,14 @@ Prize: X=(\d+), Y=(\d+)",
}
}

fn solve_integer(ax: isize, ay: isize, bx: isize, by: isize, tx: isize, ty: isize) -> usize {
// calculate b using the derived formula:
// given the system:
// a*ax + b*ay = tx
// a*bx + b*by = ty
// after elimination, we get:
// b = (ty*ax - tx*ay) / (by*ax - bx*ay)
let b = (ty * ax - tx * ay) / (by * ax - bx * ay);

// using b, solve for a:
// from a*ax + b*bx = tx -> a = (tx - b*bx) / ax
let a = (tx - b * bx) / ax;

// verify
if (ax * a + bx * b, ay * a + by * b) != (tx, ty) {
return 0;
}
a as usize * 3 + b as usize
}

// not working 🤷
fn _solve_with_good_lp(ax: f64, ay: f64, bx: f64, by: f64, tx: f64, ty: f64) -> Option<u64> {
// working for part1, but not for big number like part2 🤷 float imprecision ?
fn _solve_with_good_lp(
Machine {
a: (ax, ay),
b: (bx, by),
prize: (tx, ty),
}: Machine,
) -> Option<u64> {
use good_lp::*;
variables! {
vars:
Expand All @@ -58,8 +44,8 @@ fn _solve_with_good_lp(ax: f64, ay: f64, bx: f64, by: f64, tx: f64, ty: f64) ->
let model = vars
.minimise(a + b)
.using(default_solver)
.with(constraint!(a * ax + b * bx == tx))
.with(constraint!(a * ay + b * by == ty));
.with(constraint!(a * ax as f64 + b * bx as f64 == tx as f64))
.with(constraint!(a * ay as f64 + b * by as f64 == ty as f64));

let solution = match model.solve() {
Ok(sol) => sol,
Expand All @@ -72,36 +58,46 @@ fn _solve_with_good_lp(ax: f64, ay: f64, bx: f64, by: f64, tx: f64, ty: f64) ->
Some(a_val.round() as u64 * 3 + b_val.round() as u64)
}

fn part1(input: &str) -> usize {
let machines = Machine::from_list(input);
let mut used = 0;
for Machine { a, b, prize } in machines {
used += solve_integer(
a.0 as isize,
a.1 as isize,
b.0 as isize,
b.1 as isize,
prize.0 as isize,
prize.1 as isize,
);
// fn solve_integer(ax: isize, ay: isize, bx: isize, by: isize, tx: isize, ty: isize) -> usize {
fn calculate(
Machine {
a: (ax, ay),
b: (bx, by),
prize: (tx, ty),
}: Machine,
) -> usize {
// calculate b using the derived formula:
// given the system:
// a*ax + b*bx = tx
// a*ay + b*by = ty
// after elimination, we get:
// b = (ty*ax - tx*ay) / (by*ax - bx*ay)
let b = (ty * ax - tx * ay) / (by * ax - bx * ay);

// using b, solve for a:
// from a*ax + b*bx = tx -> a = (tx - b*bx) / ax
let a = (tx - b * bx) / ax;

// verify
if (ax * a + bx * b, ay * a + by * b) != (tx, ty) {
return 0;
}
used
a as usize * 3 + b as usize
}

fn part1(input: &str) -> usize {
Machine::from_list(input).into_iter().map(calculate).sum()
}

fn part2(input: &str) -> usize {
let machines = Machine::from_list(input);
let mut used = 0;
for Machine { a, b, prize } in machines {
used += solve_integer(
a.0 as isize,
a.1 as isize,
b.0 as isize,
b.1 as isize,
prize.0 as isize + 10000000000000,
prize.1 as isize + 10000000000000,
);
}
used
Machine::from_list(input)
.into_iter()
.map(|mut m| {
m.prize.0 += 10000000000000;
m.prize.1 += 10000000000000;
calculate(m)
})
.sum()
}

fn main() {
Expand Down Expand Up @@ -133,6 +129,6 @@ Prize: X=18641, Y=10279";
}
#[test]
fn part2() {
assert_eq!(super::part2(INPUT), 100);
assert_eq!(super::part2(INPUT), 875318608908);
}
}

0 comments on commit 944efe9

Please sign in to comment.