|
1 | 1 | package dev.jacobandersen.codechallenges.challenge.adventofcode.year2024.day13;
|
2 | 2 |
|
3 | 3 | import dev.jacobandersen.codechallenges.challenge.adventofcode.Day;
|
| 4 | +import org.ejml.simple.SimpleMatrix; |
| 5 | + |
| 6 | +import java.util.ArrayList; |
| 7 | +import java.util.Arrays; |
| 8 | +import java.util.List; |
| 9 | +import java.util.regex.Matcher; |
| 10 | +import java.util.regex.Pattern; |
4 | 11 |
|
5 | 12 | public class Day13 extends Day {
|
| 13 | + private final Pattern pattern = Pattern.compile("^.*[+=](\\d+).*[+=](\\d+)$"); |
| 14 | + |
6 | 15 | public Day13() {
|
7 | 16 | super(2024, 13, "Claw Contraption");
|
8 | 17 | }
|
9 | 18 |
|
| 19 | + record Machine(double[] x, double[] y) { |
| 20 | + private long[] solve() throws RuntimeException { |
| 21 | + final SimpleMatrix A = new SimpleMatrix(2, 2); |
| 22 | + A.set(0, 0, x[0]); |
| 23 | + A.set(0, 1, x[1]); |
| 24 | + A.set(1, 0, y[0]); |
| 25 | + A.set(1, 1, y[1]); |
| 26 | + |
| 27 | + final SimpleMatrix B = new SimpleMatrix(2, 1); |
| 28 | + B.set(0, 0, x[2]); |
| 29 | + B.set(1, 0, y[2]); |
| 30 | + |
| 31 | + final SimpleMatrix sol = A.solve(B); |
| 32 | + |
| 33 | + long solA = Math.round(sol.get(0)), solB = Math.round(sol.get(1)); |
| 34 | + |
| 35 | + double xCheck = (x[0] * solA) + (x[1] * solB); |
| 36 | + double yCheck = (y[0] * solA) + (y[1] * solB); |
| 37 | + |
| 38 | + if (Math.abs(xCheck - x[2]) < 1e-6 && Math.abs(yCheck - y[2]) < 1e-6) { |
| 39 | + return new long[] {solA, solB}; |
| 40 | + } else throw new RuntimeException("No integer solution."); |
| 41 | + } |
| 42 | + |
| 43 | + @Override |
| 44 | + public String toString() { |
| 45 | + return "Machine{" + |
| 46 | + "x=" + Arrays.toString(x) + |
| 47 | + ", y=" + Arrays.toString(y) + |
| 48 | + '}'; |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + private double[] matchLine(String line) { |
| 53 | + Matcher matcher = pattern.matcher(line); |
| 54 | + if(!matcher.matches()) throw new IllegalArgumentException(); |
| 55 | + return new double[]{Double.parseDouble(matcher.group(1)), Double.parseDouble(matcher.group(2))}; |
| 56 | + } |
| 57 | + |
| 58 | + private List<Machine> loadMachines() { |
| 59 | + List<String> lines = getInputLinesNoBlanks(); |
| 60 | + |
| 61 | + List<Machine> machines = new ArrayList<>(); |
| 62 | + for (int i = 0; i < lines.size(); i+=3) { |
| 63 | + final double[] x = new double[3], y = new double[3]; |
| 64 | + |
| 65 | + final double[] a = matchLine(lines.get(i)), b = matchLine(lines.get(i+1)), prize = matchLine(lines.get(i+2)); |
| 66 | + x[0] = a[0]; |
| 67 | + y[0] = a[1]; |
| 68 | + x[1] = b[0]; |
| 69 | + y[1] = b[1]; |
| 70 | + x[2] = prize[0]; |
| 71 | + y[2] = prize[1]; |
| 72 | + |
| 73 | + machines.add(new Machine(x, y)); |
| 74 | + } |
| 75 | + |
| 76 | + return machines; |
| 77 | + } |
| 78 | + |
| 79 | + private long countTokens(List<Machine> machines) { |
| 80 | + return machines.stream().mapToLong(machine -> { |
| 81 | + try { |
| 82 | + final long[] solution = machine.solve(); |
| 83 | + return (3 * solution[0]) + solution[1]; |
| 84 | + } catch (RuntimeException ignored) {} |
| 85 | + |
| 86 | + return 0; |
| 87 | + }).sum(); |
| 88 | + } |
| 89 | + |
10 | 90 | @Override
|
11 | 91 | public String partOne() {
|
12 |
| - getInputLinesNoBlanks().forEach(System.out::println); |
13 |
| - return ""; |
| 92 | + return String.valueOf(countTokens(loadMachines())); |
14 | 93 | }
|
15 | 94 |
|
16 | 95 | @Override
|
17 | 96 | public String partTwo() {
|
18 |
| - return ""; |
| 97 | + return String.valueOf(countTokens(loadMachines().stream().map(m -> { |
| 98 | + final double[] x = new double[] { m.x[0], m.x[1], m.x[2] + 10_000_000_000_000d }; |
| 99 | + final double[] y = new double[] { m.y[0], m.y[1], m.y[2] + 10_000_000_000_000d }; |
| 100 | + return new Machine(x, y); |
| 101 | + }).toList())); |
19 | 102 | }
|
20 | 103 | }
|
0 commit comments