It's the day after Christmas. It was a nice day, I had some friends over, we drank eggnog and watch dumb movies. It was a good time. Now to relax, by spending who knows how many hours trying to solve some of these puzzles.
This looks oddly familiar to something like the Game of Life. But it seems pretty straightforward overall. I'm imagining something that would take three passes over a 2d char array:
- Add any additional space around the field if necessary
- Record each elf that proposes to move - a
map
ofpair, vector<pair>
, with the key being the proposed location - Perform the move for any key that has only one proposed move
- If any elves moved, or were blocked, repeat
It'll be a bit more complex with having to cycle out which directions are considered in what order, but not too bad overall.
#define COORD pair<int, int>
#define MOVE_LIST map<COORD, vector<COORD>>
// ...
do {
blocked = 0;
moves = MOVE_LIST();
/// Record move proposals
for (int row = 1; row < field.size()-1; row++)
for (int col = 1; col < field[0].size()-1; col++)
{
// Elf Check
if (field[row][col] == '.') continue;
// Clear check
bool clear = true;
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
{
if (i == 0 && j == 0) continue;
if (field[row+i][col+j] == '#')
{
clear = false;
break;
}
}
if (clear) continue;
// Move proposal
bool canMove = false;
for (char d: dirs)
{
if (canMove) break;
switch(d)
{
case 'N':
if ( field[row-1][col-1] == '.'
&& field[row-1][col ] == '.'
&& field[row-1][col+1] == '.')
{
moves[COORD(row-1, col)].push_back(COORD(row, col));
canMove = true;
}
break;
case 'S': // Check South
case 'E': // Check East
case 'W': // Check West
}
}
if (!canMove) blocked++;
}
rotate(dirs.begin(), dirs.begin()+1, dirs.end());
/// Perform moves
for (auto proposal: moves)
{
if (proposal.second.size() > 1) continue;
field[proposal.first.first][proposal.first.second] = '#';
field[proposal.second[0].first][proposal.second[0].second] = '.';
}
} while (++iterations < 10);
This works pretty quickly and reliably!
The second part makes sense - just keep running the simulation until the elves no longer need to move around. Just a few modifications to print out the number of iterations, let it run for a minute or two, and it works just as well.
In retrospect, maybe I would have done better converting this all to a vector<bool>
or something instead of messing with strings. But eh, it still ran quick enough.