Add solution for "Day 19: Linen Layout", part 2
This commit is contained in:
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user