Add solution for "Day 19: Linen Layout", part 2

This commit is contained in:
2025-06-02 22:20:15 +02:00
parent 12fdc184cf
commit 2afa527a85
5 changed files with 47 additions and 27 deletions

View File

@@ -31,10 +31,12 @@ void LinenLayout::processDataLine(const std::string& line)
{
if (isReadingDesigns_)
{
if (patterns_.isPossible(line))
auto nArrangements = patterns_.countArrangements(line);
if (nArrangements > 0)
{
part1++;
}
part2 += nArrangements;
}
else if (line.empty())
{

View File

@@ -46,50 +46,48 @@ void LinenTowelPatterns::add(const std::string& towelPattern)
patterns_[current].second = true;
}
bool LinenTowelPatterns::isPossible(const std::string& design)
int64_t LinenTowelPatterns::countArrangements(const std::string& design)
{
std::vector<bool> canStartFrom(design.size(), false);
std::vector<bool> canStartFrom(design.size() + 1, false);
canStartFrom[0] = true;
std::set<size_t> unexploredStart;
unexploredStart.insert(0);
std::vector<int64_t> nArrangements(design.size() + 1, 0);
nArrangements[0] = 1;
size_t startPosition{ 0 };
while (!unexploredStart.empty())
while (startPosition < design.size())
{
size_t designPosition = *unexploredStart.rbegin();
unexploredStart.erase(designPosition);
size_t designPosition{ startPosition };
size_t i{ stripes_[design[designPosition]] };
while (++designPosition < design.size() && patterns_[i].first > 0)
{
if (patterns_[i].second && !canStartFrom[designPosition])
// Checks if there is a towel with the current accumulated stripe pattern.
if (patterns_[i].second)
{
// The current accumulated stripe pattern exists and it ends at a new position within the design.
canStartFrom[designPosition] = true;
unexploredStart.insert(designPosition);
nArrangements[designPosition] += nArrangements[startPosition];
}
// Checks if the current accumulated stripe pattern can be extended further.
if (patterns_[i].first > 0)
{
// The current accumulated stripe pattern can be extended further.
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)
{
if (designPosition == design.size())
{
// The current accumulated stripe pattern exists and finishes the design.
return true;
}
else if (!canStartFrom[designPosition])
{
// The current accumulated stripe pattern exists and it ends at a new position within the design.
canStartFrom[designPosition] = true;
unexploredStart.insert(designPosition);
}
canStartFrom[designPosition] = true;
nArrangements[designPosition] += nArrangements[startPosition];
}
// Seeks the next start position.
do
{
startPosition++;
} while (startPosition < canStartFrom.size() && !canStartFrom[startPosition]);
}
return false;
return *nArrangements.rbegin();
}
void LinenTowelPatterns::addBranch()