From bd5df5d01999e3b8f4d515d4bc133fa3e1dd24ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20M=C3=BCller?= Date: Tue, 18 Feb 2025 15:01:11 +0100 Subject: [PATCH] Add solution for "Day 13: Claw Contraption", part 1 --- include/aoc/ClawContraption.hpp | 35 +++++++++++ src/ClawContraption.cpp | 102 ++++++++++++++++++++++++++++++++ src/Program.cpp | 2 + tests/src/TestCases.cpp | 14 +++++ 4 files changed, 153 insertions(+) create mode 100644 include/aoc/ClawContraption.hpp create mode 100644 src/ClawContraption.cpp diff --git a/include/aoc/ClawContraption.hpp b/include/aoc/ClawContraption.hpp new file mode 100644 index 0000000..5835ba9 --- /dev/null +++ b/include/aoc/ClawContraption.hpp @@ -0,0 +1,35 @@ +// Solutions to the Advent Of Code 2024. +// Copyright (C) 2025 Stefan Müller +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . + +#pragma once + +#include +#include + +class ClawContraption : public Solver +{ +public: + virtual const std::string getPuzzleName() const override; + virtual const int getPuzzleDay() const override; + virtual void processDataLine(const std::string& line) override; + virtual void finish() override; +private: + Point2 buttonA_; + Point2 buttonB_; + 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); +}; diff --git a/src/ClawContraption.cpp b/src/ClawContraption.cpp new file mode 100644 index 0000000..9b2a713 --- /dev/null +++ b/src/ClawContraption.cpp @@ -0,0 +1,102 @@ +// Solutions to the Advent Of Code 2024. +// Copyright (C) 2025 Stefan Müller +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with +// this program. If not, see . + +#include + +#include + +const std::string ClawContraption::getPuzzleName() const +{ + return "Claw Contraption"; +} + +const int ClawContraption::getPuzzleDay() const +{ + return 13; +} + +void ClawContraption::processDataLine(const std::string& line) +{ + if (!line.empty()) + { + std::istringstream stream{ line }; + std::string token; + char c; + int x; + int y; + + stream >> token; + if (token == "Button") + { + stream >> c; + std::getline(stream, token, '+'); + stream >> x; + std::getline(stream, token, '+'); + stream >> y; + if (c == 'A') + { + buttonA_ = { x, y }; + } + else + { + buttonB_ = { x, y }; + } + } + else + { + std::getline(stream, token, '='); + stream >> x; + std::getline(stream, token, '='); + stream >> y; + part1 += calcTokenCost(buttonA_, buttonB_, { x, y }); + } + } +} + +void ClawContraption::finish() +{ +} + +constexpr int ClawContraption::getNMaxButtonPushes() +{ + return 100; +} + +constexpr int ClawContraption::getButtonACost() +{ + return 3; +} + +constexpr int ClawContraption::getButtonBCost() +{ + return 1; +} + +long long int ClawContraption::calcTokenCost(const Point2& buttonA, const Point2& buttonB, const Point2& prize) +{ + long long int p{ prize.y * buttonB.x - prize.x * 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()) + { + return 0; + } + long long int b{ (prize.x - a * buttonA.x) / buttonB.x }; + if (b > getNMaxButtonPushes()) + { + return 0; + } + return a * getButtonACost() + b * getButtonBCost(); +} diff --git a/src/Program.cpp b/src/Program.cpp index 9e20db1..6cef544 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include void Program::run() @@ -63,6 +64,7 @@ void Program::runSolvers() runSolver(solverEngine); runSolver(solverEngine); runSolver(solverEngine); + runSolver(solverEngine); runSolver(solverEngine); } diff --git a/tests/src/TestCases.cpp b/tests/src/TestCases.cpp index e2afe14..680c526 100644 --- a/tests/src/TestCases.cpp +++ b/tests/src/TestCases.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #define REQUIRE_MESSAGE(cond, msg) if (!(cond)) { INFO(msg); REQUIRE(cond); } @@ -206,6 +207,19 @@ TEST_CASE("[GardenGroupsTests]") } } +TEST_CASE("[ClawContraptionTests]") +{ + TestContext test; + SECTION("FullData") + { + test.run(std::make_unique(), 36571, 0, test.getInputPaths()); + } + SECTION("ExampleData") + { + test.run(std::make_unique(), 480, 0, test.getExampleInputPaths()); + } +} + TEST_CASE("[LanPartyTests]") { TestContext test;