--- Day 14: Cycles ---

December 14

Listening to: Low Poly Breaks [DISC. 3] // VIDEO GAME DNB & AMBIENT JUNGLE MIX (PS1/PS2/N64/GAMECUBE/DREAMCAST)


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;
        }
    }
}

Time taken: 1 hour

My solutions for today's puzzles