diff --git a/answers.yaml b/answers.yaml index 32c210d..3fd6621 100644 --- a/answers.yaml +++ b/answers.yaml @@ -95,3 +95,6 @@ 1: 1: 997 2: 5_978 + 2: + 1: 19_605_500_130 + 2: 36_862_281_418 diff --git a/inputs.json b/inputs.json index a55e5b9..907b1c5 100644 --- a/inputs.json +++ b/inputs.json @@ -28,5 +28,6 @@ "2024-05.txt", "2024-06.txt", "2024-07.txt", - "2025-01.txt" + "2025-01.txt", + "2025-02.txt" ] diff --git a/inputs.tar.gpg b/inputs.tar.gpg index 5c98940..ee5a463 100644 Binary files a/inputs.tar.gpg and b/inputs.tar.gpg differ diff --git a/solvers.yaml b/solvers.yaml index dc10f18..719e3bb 100644 --- a/solvers.yaml +++ b/solvers.yaml @@ -93,3 +93,6 @@ 1: 1: cpp 2: cpp + 2: + 1: cpp + 2: cpp diff --git a/solvers/cpp/src/bin/y2025_d02.cpp b/solvers/cpp/src/bin/y2025_d02.cpp new file mode 100644 index 0000000..11d633d --- /dev/null +++ b/solvers/cpp/src/bin/y2025_d02.cpp @@ -0,0 +1,97 @@ +#include "my_chunk_view.hpp" +#include "my_fold_left_first.hpp" +#include "solver.hpp" +#include "utils.hpp" + +#include + +#include + +namespace ranges = std::ranges; +namespace views = std::views; + +namespace { + +class Id final { + public: + explicit Id(uint64_t id) : _id(id), _idStr(std::to_string(id)) {} + + [[nodiscard]] auto id() const { return _id; } + [[nodiscard]] auto idStr() const -> const std::string& { return _idStr; } + + private: + uint64_t _id; + std::string _idStr; +}; + +auto rangesLine(const std::string_view inputStr) { + auto lines = splitLinesUntilEmpty(inputStr) | ranges::to(); + if (lines.size() != 1) { + throw std::runtime_error("Expected only one line of input"); + } + return lines.at(0); +} + +auto solve(const std::string_view inputStr, auto&& filterIds) { + auto line = rangesLine(inputStr); + return MyFoldLeftFirst( + line | views::split(',') | + views::transform([filterIds](auto&& idRange) { + auto parts = + idRange | views::split('-') | ranges::to(); + auto start = convert(parts.at(0)); + auto end = convert(parts.at(1)); + spdlog::debug("Checking range [{}, {}]", start, end); + auto ids = + filterIds(views::iota(start, end + 1) | + views::transform([](auto id) { return Id(id); })); + return MyFoldLeftFirst(ids | views::transform([](const Id& id) { + spdlog::debug("Found invalid ID: {}", + id.idStr()); + return id.id(); + }), + std::plus{}) + .value_or(uint64_t{}); + }), + std::plus{}) + .value_or(uint64_t{}); +} + +} // namespace + +auto solver::p1(const std::string_view inputStr) -> Answer { + return solve(inputStr, [](auto&& ids) { + return ids | views::filter([](const Id& id) { + return id.idStr().length() % 2 == 0; + }) | + views::filter([](const Id& id) { + auto view = std::string_view(id.idStr()); + return view.substr(0, view.length() / 2) == + view.substr(view.length() / 2); + }); + }); +} + +auto solver::p2(const std::string_view inputStr) -> Answer { + return solve(inputStr, [](auto&& ids) { + return ids | views::filter([](const Id& id) { + auto view = std::string_view(id.idStr()); + for (auto length : views::iota(std::size_t{1}, view.size())) { + if (view.size() % length != 0) { + continue; + } + auto value = view.substr(0, length); + auto nonMatching = + view | MyChunk(length) | views::drop(1) | + views::transform( + [](auto&& part) { return std::string_view(part); }) | + views::filter([value](auto&& part) { return part != value; }); + + if (ranges::empty(nonMatching)) { + return true; + } + } + return false; + }); + }); +} diff --git a/solvers/cpp/src/bin/y2025_d02.test.cpp b/solvers/cpp/src/bin/y2025_d02.test.cpp new file mode 100644 index 0000000..b7dcf4d --- /dev/null +++ b/solvers/cpp/src/bin/y2025_d02.test.cpp @@ -0,0 +1,24 @@ +#include "solver.hpp" +#include "test_utils.hpp" + +#include + +#include + +using namespace std::string_view_literals; + +using T2025Day2 = TestFixture; + +constexpr auto exampleInput = processExampleInput(R"input( +11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124 +)input"sv); + +TEST_F(T2025Day2, p1) { + constexpr auto exampleResult = 1'227'775'554; + verifyResult(solver::p1(exampleInput), exampleResult); +} + +TEST_F(T2025Day2, p2) { + constexpr auto exampleResult = 4'174'379'265; + verifyResult(solver::p2(exampleInput), exampleResult); +}