I have a feeling today's puzzle was at least in part inspiried by the James Webb Telescope which finally went live in the past year. I remember reading that they needed to calibrate all of it's consituent mirrors before it would be able to be properly focused, very similar to today's problem. It also looks like a version of the classic Ice floor puzzle found in a lot of video games.
There's a few different ways this could be done, but the way I plan to implement the sliding is to simply iterate one slide-step (meaning, check each row/column only once per iteration), and simply repeat that step until one iteration results in zero changes.
bool SlideNorth(vector<string>* floor)
{
bool changes = false;
// Note: Skip row 0
for (int x = 1; x < floor->size(); x++)
{
for (int y = 0; y < floor->at(x).size(); y++)
{
if (floor->at(x)[y] == 'O' && floor->at(x-1)[y] == '.')
{
floor->at(x)[y] = '.';
floor->at(x-1)[y] = 'O';
changes = true;
}
}
}
return changes;
}
From there, just calculate load from the row index for each O
;
Okay... I was predicting it to do other directions as well for part 2, but I didn't predict this: Do it one-billion times! I can already tell that doing it that many times directly likely would take unreasonably long (though I may just try it anyway), so it's probably another candidate for memoization.
First step, implement the other four directions. Just copied the above function, changed some x/y and +/-, and it's all good.
Next, to cycle through it all.
for (int i = 0; i < 1000000000; i++)
{
if (i % 100000 == 0) cout << "Step " << i << endl;
Cycle(floor);
}
It takes a few seconds to get through even 100,000 steps. If I left it for an hour I could probably just go walk my dog and it'll be about halfway done. But that wouldn't be right.
I have a feeling that this probably goes into a cycle - eventually. I just need to find where that cycle starts, and I can just math my way to the right state.
vector<vector<string>> states;
while (true) {
states.push_back(vector<string>(*floor));
Cycle(floor);
for (int i = 0; i < states.size(); i++)
{
if (FloorEqual(states[i], *floor))
{
int cycleSize = states.size() - i;
uint64_t finalStateIndex = (CYCLE_COUNT - i) % cycleSize;
finalStateIndex += i;
vector<string> finalState = states[finalStateIndex];
// Calculate stress
uint64_t load = 0;
for (int i = 0; i < finalState.size(); i++)
{
for (auto c : finalState[i])
{
if (c == 'O') load += finalState.size() - i;
}
}
cout << endl << "Output: " << load << endl;
return 0;
}
}
}