|
1 | | -import { init } from "z3-solver"; |
2 | | - |
| 1 | +// px = a * ax + b * bx |
| 2 | +// py = a * ay + b * by |
| 3 | +// |
| 4 | +// b = (px - a * ax) / bx |
| 5 | +// py = a * ay + (px - a * ax) / bx * by |
| 6 | +// py = a * ay + px * by / bx - a * ax * by / bx |
| 7 | +// a * ay + px * by / bx - a * ax * by / bx - py = 0 |
| 8 | +// a * ay - a * ax * by / bx = py - px * by / bx |
| 9 | +// a * (ay - ax * by / bx) = py - px * by / bx |
| 10 | +// a = (py - px * by / bx) / (ay - ax * by / bx) |
3 | 11 | function solve({ ax, ay, bx, by, px, py }) { |
4 | | - for (let a = 0; a <= 100; a++) { |
5 | | - for (let b = 0; b <= 100; b++) { |
6 | | - const x = a * ax + b * bx; |
7 | | - const y = a * ay + b * by; |
8 | | - if (x === px && y === py) { |
9 | | - return a * 3 + b; |
10 | | - } |
11 | | - } |
12 | | - } |
13 | | - return 0; |
| 12 | + const b = (py * ax - px * ay) / (by * ax - bx * ay); |
| 13 | + const a = (px - b * bx) / ax; |
| 14 | + if (Math.floor(a) === a && Math.floor(b) === b) return a * 3 + b; |
| 15 | + else return 0; |
14 | 16 | } |
15 | 17 |
|
16 | | -export function part1(input) { |
17 | | - let machines = input.split("\n\n").map(group => { |
| 18 | +function parse(input) { |
| 19 | + return input.split("\n\n").map(group => { |
18 | 20 | const [a, b, prize] = group.split("\n"); |
19 | 21 | const [, ax, ay] = a.match(/X\+(\d+), Y\+(\d+)/); |
20 | 22 | const [, bx, by] = b.match(/X\+(\d+), Y\+(\d+)/); |
21 | 23 | const [, px, py] = prize.match(/X=(\d+), Y=(\d+)/); |
22 | 24 | return { ax: +ax, ay: +ay, bx: +bx, by: +by, px: +px, py: +py }; |
23 | 25 | }); |
24 | | - const price = machines.map(solve).reduce((a, b) => a + b, 0); |
25 | | - return price; |
26 | 26 | } |
27 | 27 |
|
28 | | -async function solve2({ ax, ay, bx, by, px, py }) { |
29 | | - px += 10000000000000; |
30 | | - py += 10000000000000; |
31 | | - const { Context } = await init(); |
32 | | - const { Solver, Int } = Context("main"); |
33 | | - const solver = new Solver(); |
34 | | - const a = Int.const(`a`); |
35 | | - const b = Int.const(`b`); |
36 | | - solver.add(a.ge(0)); |
37 | | - solver.add(b.ge(0)); |
38 | | - solver.add(a.mul(ax).add(b.mul(bx)).eq(px)); |
39 | | - solver.add(a.mul(ay).add(b.mul(by)).eq(py)); |
40 | | - if ((await solver.check()) === "sat") { |
41 | | - const model = solver.model(); |
42 | | - const result = model.eval(a.mul(3).add(b)).toString(); |
43 | | - return +result; |
44 | | - } |
45 | | - return 0; |
| 28 | +export function part1(input) { |
| 29 | + let machines = parse(input); |
| 30 | + return machines.map(solve).reduce((a, b) => a + b, 0); |
46 | 31 | } |
47 | 32 |
|
48 | | -export async function part2(input) { |
49 | | - let machines = input.split("\n\n").map(group => { |
50 | | - const [a, b, prize] = group.split("\n"); |
51 | | - const [, ax, ay] = a.match(/X\+(\d+), Y\+(\d+)/); |
52 | | - const [, bx, by] = b.match(/X\+(\d+), Y\+(\d+)/); |
53 | | - const [, px, py] = prize.match(/X=(\d+), Y=(\d+)/); |
54 | | - return { ax: +ax, ay: +ay, bx: +bx, by: +by, px: +px, py: +py }; |
55 | | - }); |
56 | | - let price = 0; |
57 | | - for (const machine of machines) { |
58 | | - price += await solve2(machine); |
59 | | - } |
60 | | - return price; |
| 33 | +export function part2(input) { |
| 34 | + let machines = parse(input); |
| 35 | + machines = machines.map(m => ({ ...m, px: m.px + 10000000000000 })); |
| 36 | + machines = machines.map(m => ({ ...m, py: m.py + 10000000000000 })); |
| 37 | + return machines.map(solve).reduce((a, b) => a + b, 0); |
61 | 38 | } |
0 commit comments