From 973f62163d1ae998bd44ccb691f1672365e7c096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20M=C3=BCller?= Date: Tue, 18 Feb 2025 16:11:29 +0100 Subject: [PATCH] Add solution for "Day 13: Claw Contraption", part 2 --- README.md | 6 ++++++ include/aoc/ClawContraption.hpp | 4 +++- src/ClawContraption.cpp | 20 ++++++++++++++------ tests/src/TestCases.cpp | 4 ++-- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0644b36..f5d628d 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,12 @@ The perimeter of a region is the sum of neighbors for all plots encountered duri Adding up the products of area and perimeter, or area and corner count, per region gives us the solution. +### Day 13: Claw Contraption + +:mag_right: Puzzle: , :white_check_mark: Solver: [`ClawContraption.cpp`](src/ClawContraption.cpp) + +For each claw machine, we have to solve a simple linear equation system to get the number of required button pushes. Conveniently, for the given data, all of these systems have a unique solution. However, some solutions have to be excluded because the number of button pushes is not integer, or because the solutions are too high for part 1. The required integer tests are done by performing integer division, and comparing the dividend with the product of the integer quotient and the divisor. + ## Thanks * [Alexander Brouwer](https://github.com/Bromvlieg) for getting the project set up with CMake. diff --git a/include/aoc/ClawContraption.hpp b/include/aoc/ClawContraption.hpp index 5835ba9..b06c945 100644 --- a/include/aoc/ClawContraption.hpp +++ b/include/aoc/ClawContraption.hpp @@ -31,5 +31,7 @@ class ClawContraption : public Solver static constexpr int getNMaxButtonPushes(); static constexpr int getButtonACost(); static constexpr int getButtonBCost(); - long long int calcTokenCost(const Point2& buttonA, const Point2& buttonB, const Point2& prize); + static constexpr long long int getConversionCorrection(); + long long int calcTokenCost(const Point2& buttonA, const Point2& buttonB, const Point2& prize, + const long long int offset); }; diff --git a/src/ClawContraption.cpp b/src/ClawContraption.cpp index 9b2a713..3241b5c 100644 --- a/src/ClawContraption.cpp +++ b/src/ClawContraption.cpp @@ -60,7 +60,8 @@ void ClawContraption::processDataLine(const std::string& line) stream >> x; std::getline(stream, token, '='); stream >> y; - part1 += calcTokenCost(buttonA_, buttonB_, { x, y }); + part1 += calcTokenCost(buttonA_, buttonB_, { x, y }, 0); + part2 += calcTokenCost(buttonA_, buttonB_, { x, y }, getConversionCorrection()); } } } @@ -84,17 +85,24 @@ constexpr int ClawContraption::getButtonBCost() return 1; } -long long int ClawContraption::calcTokenCost(const Point2& buttonA, const Point2& buttonB, const Point2& prize) +constexpr long long int ClawContraption::getConversionCorrection() { - long long int p{ prize.y * buttonB.x - prize.x * buttonB.y }; + return 10000000000000; +} + +long long int ClawContraption::calcTokenCost(const Point2& buttonA, const Point2& buttonB, const Point2& prize, + const long long int offset) +{ + long long int p{ (prize.y + offset) * buttonB.x - (prize.x + offset) * buttonB.y }; long long int q{ buttonA.y * buttonB.x - buttonA.x * buttonB.y }; long long int a{ p / q }; - if (a * q != p || a > getNMaxButtonPushes()) + if (a * q != p || (offset == 0 && a > getNMaxButtonPushes())) { return 0; } - long long int b{ (prize.x - a * buttonA.x) / buttonB.x }; - if (b > getNMaxButtonPushes()) + long long int r{ prize.x + offset - a * buttonA.x }; + long long int b{ r / buttonB.x }; + if (b * buttonB.x != r || (offset == 0 && b > getNMaxButtonPushes())) { return 0; } diff --git a/tests/src/TestCases.cpp b/tests/src/TestCases.cpp index 680c526..8697987 100644 --- a/tests/src/TestCases.cpp +++ b/tests/src/TestCases.cpp @@ -212,11 +212,11 @@ TEST_CASE("[ClawContraptionTests]") TestContext test; SECTION("FullData") { - test.run(std::make_unique(), 36571, 0, test.getInputPaths()); + test.run(std::make_unique(), 36571, 85527711500010, test.getInputPaths()); } SECTION("ExampleData") { - test.run(std::make_unique(), 480, 0, test.getExampleInputPaths()); + test.run(std::make_unique(), 480, 875318608908, test.getExampleInputPaths()); } }