// 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 LinenTowelPatterns::LinenTowelPatterns() : patterns_{}, stripes_{ { 'w', 0 }, { 'u', 1 }, { 'b', 2 }, { 'r', 3 }, { 'g', 4 } } { addBranch(); } void LinenTowelPatterns::add(const std::string& towelPattern) { size_t current{ 0 }; size_t next{ 0 }; for (const char stripe : towelPattern) { if (next >= patterns_.size()) { patterns_[current].first = next; addBranch(); } current = next + stripes_[stripe]; next = patterns_[current].first > 0 ? patterns_[current].first : patterns_.size(); } patterns_[current].second = true; } int64_t LinenTowelPatterns::countArrangements(const std::string& design) { std::vector canStartFrom(design.size() + 1, false); canStartFrom[0] = true; std::vector nArrangements(design.size() + 1, 0); nArrangements[0] = 1; size_t startPosition{ 0 }; while (startPosition < design.size()) { size_t designPosition{ startPosition }; size_t i{ stripes_[design[designPosition]] }; while (++designPosition < design.size() && patterns_[i].first > 0) { // Checks if there is a towel with the current accumulated stripe pattern. if (patterns_[i].second) { canStartFrom[designPosition] = true; nArrangements[designPosition] += nArrangements[startPosition]; } // Checks if the current accumulated stripe pattern can be extended further. if (patterns_[i].first > 0) { i = patterns_[i].first + stripes_[design[designPosition]]; } } // Checks if there is a towel with the current accumulated stripe pattern, after its final extension. if (patterns_[i].second) { canStartFrom[designPosition] = true; nArrangements[designPosition] += nArrangements[startPosition]; } // Seeks the next start position. do { startPosition++; } while (startPosition < canStartFrom.size() && !canStartFrom[startPosition]); } return nArrangements.back(); } void LinenTowelPatterns::addBranch() { for (size_t i = 0; i < stripes_.size(); i++) { patterns_.emplace_back(std::make_pair(0, false)); } }