From a61a88b4448fa192d98b3d939d6024b7fdc3d1b6 Mon Sep 17 00:00:00 2001 From: Sander in 't Hout Date: Sat, 14 Dec 2024 02:07:09 +0100 Subject: [PATCH] Add AoC 2024 day 13 solver --- assets/advent_of_code/2024_13_sample.txt | 15 +++++ .../advent_of_code/2024/_all_solvers.dart | 1 + .../advent_of_code/2024/day_13_solver.dart | 58 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 assets/advent_of_code/2024_13_sample.txt create mode 100644 lib/solvers/advent_of_code/2024/day_13_solver.dart diff --git a/assets/advent_of_code/2024_13_sample.txt b/assets/advent_of_code/2024_13_sample.txt new file mode 100644 index 0000000..444a287 --- /dev/null +++ b/assets/advent_of_code/2024_13_sample.txt @@ -0,0 +1,15 @@ +Button A: X+94, Y+34 +Button B: X+22, Y+67 +Prize: X=8400, Y=5400 + +Button A: X+26, Y+66 +Button B: X+67, Y+21 +Prize: X=12748, Y=12176 + +Button A: X+17, Y+86 +Button B: X+84, Y+37 +Prize: X=7870, Y=6450 + +Button A: X+69, Y+23 +Button B: X+27, Y+71 +Prize: X=18641, Y=10279 \ No newline at end of file diff --git a/lib/solvers/advent_of_code/2024/_all_solvers.dart b/lib/solvers/advent_of_code/2024/_all_solvers.dart index 0b9230f..addcf7b 100644 --- a/lib/solvers/advent_of_code/2024/_all_solvers.dart +++ b/lib/solvers/advent_of_code/2024/_all_solvers.dart @@ -6,3 +6,4 @@ export 'day_05_solver.dart'; export 'day_06_solver.dart'; export 'day_11_solver.dart'; export 'day_12_solver.dart'; +export 'day_13_solver.dart'; diff --git a/lib/solvers/advent_of_code/2024/day_13_solver.dart b/lib/solvers/advent_of_code/2024/day_13_solver.dart new file mode 100644 index 0000000..ce71d23 --- /dev/null +++ b/lib/solvers/advent_of_code/2024/day_13_solver.dart @@ -0,0 +1,58 @@ +import 'package:h3x_devtools/solvers/advent_of_code/2024/aoc_2024_solver.dart'; + +typedef _ClawMachineAnalysis = ({int buttonAX, int buttonAY, int buttonBX, int buttonBY, int priceX, int priceY}); + +class Day13Solver extends AdventOfCode2024Solver { + + @override + final int dayNumber = 13; + + @override + String getSolution(String input) { + String splitString = input.contains('\r\n\r\n') ? '\r\n\r\n' : input.contains('\r\r') ? '\r\r' : '\n\n'; + List<_ClawMachineAnalysis> clawMachineAnalysis = input.split(splitString).map((lineSet) { + List> matches = RegExp(r'X\+(\d*), Y\+(\d*)|X=(\d*), Y=(\d*)').allMatches(lineSet).map((e) => e.groups([0, 1, 2, 3, 4])).toList(); + return (buttonAX: int.parse(matches[0][1]!), buttonAY: int.parse(matches[0][2]!), buttonBX: int.parse(matches[1][1]!), buttonBY: int.parse(matches[1][2]!), priceX: int.parse(matches[2][3]!), priceY: int.parse(matches[2][4]!)); + }).toList(); + + // Part 1 + int usedTokensPart1 = 0; + for (({int buttonAX, int buttonAY, int buttonBX, int buttonBY, int priceX, int priceY}) analysis in clawMachineAnalysis) { + usedTokensPart1 += _getUsedTokens(analysis, false) ?? 0; + } + + // Part 2 + int usedTokensPart2 = 0; + for (({int buttonAX, int buttonAY, int buttonBX, int buttonBY, int priceX, int priceY}) analysis in clawMachineAnalysis) { + usedTokensPart2 += _getUsedTokens(analysis, true) ?? 0; + } + + return 'Fewest tokens: $usedTokensPart1, fewest tokens correct: $usedTokensPart2'; + } + +} + +int? _getUsedTokens(_ClawMachineAnalysis analysis, bool part2) { + double a1 = analysis.buttonAX.toDouble(), b1 = analysis.buttonBX.toDouble(), equals1 = analysis.priceX.toDouble() + (part2 ? 10000000000000 : 0); + double a2 = analysis.buttonAY.toDouble(), b2 = analysis.buttonBY.toDouble(), equals2 = analysis.priceY.toDouble() + (part2 ? 10000000000000 : 0); + + // Use method of elimination + double elimFactor = -a1 / a2; + double b2Elim = b2 * elimFactor; + double equalsElim = equals2 * elimFactor; + + double bAfterElim = b1 + b2Elim; + double equalsAfterElim = equals1 + equalsElim; + + double bButtonPresses = equalsAfterElim / bAfterElim; + double aButtonPresses = (equals1 - b1 * bButtonPresses) / a1; + + const double epsilon = 0.001; + if ((aButtonPresses - aButtonPresses.round()).abs() <= epsilon && + (bButtonPresses - bButtonPresses.round()).abs() <= epsilon) { + // Valid result + return aButtonPresses.round() * 3 + bButtonPresses.round(); + } + + return null; +}