// Solutions to the Advent Of Code 2024. // Copyright (C) 2024 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 #include #include PrintQueue::PrintQueue() : Solver{}, pageNoMapIndex_{ 0 }, isProcessingOrderingRules_{ true }, orderingRules_{} { for (size_t i = 0; i <= maxPageNo_; i++) { pageNoMap_[i] = -1; } for (size_t i = 0; i < nPages_; i++) { for (size_t j = 0; j < nPages_; j++) { orderingRules_[i][j] = false; } } } const std::string PrintQueue::getPuzzleName() const { return "Day 5: Print Queue"; } const std::string PrintQueue::getInputFileName() const { return "print_queue.txt"; } void PrintQueue::processDataLine(const std::string& line) { if (isProcessingOrderingRules_) { if (line.empty()) { isProcessingOrderingRules_ = false; } else { processOrderingRule(line); } } else { processUpdatePages(line); } } void PrintQueue::finish() { } size_t PrintQueue::getMapped(const int pageNo) { if (pageNoMap_[pageNo] < 0) { pageNoMap_[pageNo] = pageNoMapIndex_++; } return pageNoMap_[pageNo]; } void PrintQueue::processOrderingRule(const std::string& line) { auto pos{ line.find("|") }; auto before{ std::stoi(line.substr(0, pos)) }; auto after{ std::stoi(line.substr(pos + 1)) }; orderingRules_[getMapped(before)][getMapped(after)] = true; } void PrintQueue::processUpdatePages(const std::string& line) { std::vector pages{}; std::stringstream stream{ line }; std::string token; auto isCorrectOrder{ true }; // We completely construct 'pages' for part 2, even if the ordering is not correct. while (std::getline(stream, token, ',')) { size_t page = std::stoi(token); size_t i{ 0 }; while (isCorrectOrder && i < pages.size()) { isCorrectOrder = !orderingRules_[getMapped(page)][getMapped(pages[i])]; i++; } pages.push_back(page); } if (isCorrectOrder) { part1 += pages[pages.size() / 2]; } else { // This works because the input defines a complete ordering on the occurring // page numbers. std::sort(pages.begin(), pages.end(), [&](int const& a, int const& b) { return orderingRules_[getMapped(a)][getMapped(b)]; }); part2 += pages[pages.size() / 2]; } }