Add solution for "Day 13: Claw Contraption", part 2

This commit is contained in:
Stefan Müller 2025-02-18 16:11:29 +01:00
parent e6a132521b
commit 973f62163d
4 changed files with 25 additions and 9 deletions

View File

@ -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: <https://adventofcode.com/2024/day/13>, :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.

View File

@ -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);
};

View File

@ -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;
}

View File

@ -212,11 +212,11 @@ TEST_CASE("[ClawContraptionTests]")
TestContext test;
SECTION("FullData")
{
test.run(std::make_unique<ClawContraption>(), 36571, 0, test.getInputPaths());
test.run(std::make_unique<ClawContraption>(), 36571, 85527711500010, test.getInputPaths());
}
SECTION("ExampleData")
{
test.run(std::make_unique<ClawContraption>(), 480, 0, test.getExampleInputPaths());
test.run(std::make_unique<ClawContraption>(), 480, 875318608908, test.getExampleInputPaths());
}
}