I caught a pretty severe cold a few days ago, and haven't been up to even looking at code, let alone working on any of AoC until now, the 16th. Doubt I have any chance of catching up now, but still, I'm not giving up!
For part one this looks pretty simple. Map out a bunch of nodes (can really just put these into a map?) and repeat until the end is found.
string directions;
map<string, pair<string, string>> wasteland;
// ... parsing logic
string curNode = "AAA";
int numSteps = 0;
while (curNode != "ZZZ")
{
curNode = directions[numSteps++ % directions.length()] == 'L' ?
wasteland[curNode].first :
wasteland[curNode].second;
}
If you pardon the ternary, it works pretty well!
... ugh, this one is going to be particularly annoying now, now that I have to follow a large number of paths. I have a feeling that this might be an efficiency problem even. But I'll go the naive route first, just in case it really is that easy.
bool allEnd = false;
int numSteps = 0;
while (!allEnd)
{
bool goLeft = directions[numSteps % directions.length()] == 'L';
for (int i = 0; i < paths.size(); i++)
{
paths[i] = goLeft ? wasteland[paths[i]].first : wasteland[paths[i]].second;
}
numSteps++;
allEnd = true;
for (auto path: paths)
{
if (path[2] != 'Z') allEnd = false;
}
}
That works, technically, but it's taking so long to run that I'm not sure it's the right solution....
Each route on the full input takes in the order of the same number of steps. Maybe they all loop? If they loop, then just taking the multiple of the step counts (or least common multiple) will work?
int64_t pathNum = 1, totalSteps = 1;
for (auto curNode: paths)
{
int64_t numSteps = 0;
while (curNode[2] != 'Z')
{
curNode = directions[numSteps++ % directions.length()] == 'L' ?
wasteland[curNode].first :
wasteland[curNode].second;
}
totalSteps = std::lcm(totalSteps, numSteps);
}
Huh. That did it nearly instantly. Neat.