--- Day 18: Obsidian ---

December 18

Listening to: radio cutman 💾 chill beats & videogame music


I made some eggnog a few weeks ago, and just tried a sample of it today after letting it age. Whew. It's strong. Hopefully I don't get food poisoning or something, because I made like a gallon...


This one doesn't seem too bad at first glance. The naïve solution that comes to mind is to put each into an array (maybe a 3d bool array?). Iterate over the array, and count up the number of adjacent true values in each cardinal direction. Add 6-count to a total. It looks like in my input there's nothing larger than maybe 18, so to be safe it'll be a 20^3 (8000) bool array. Small enough to just iterate over quickly.

vector<vector<vector<bool>>> drop;
uint64_t surfaceArea = 0;

for (int x = 0; x < DROP_SIZE; x++)
for (int y = 0; y < DROP_SIZE; y++)
for (int z = 0; z < DROP_SIZE; z++)
{
    if (!drop[x][y][z]) continue;
    
    surfaceArea += 6;
    if (x+1 < DROP_SIZE && drop[x+1][y][z]) surfaceArea--;
    if (x   > 0         && drop[x-1][y][z]) surfaceArea--;
    if (y+1 < DROP_SIZE && drop[x][y+1][z]) surfaceArea--;
    if (y   > 0         && drop[x][y-1][z]) surfaceArea--;
    if (z+1 < DROP_SIZE && drop[x][y][z+1]) surfaceArea--;
    if (z   > 0         && drop[x][y][z-1]) surfaceArea--;
}

That was... desceptively easy for a part one this late.


Yep, that makes sense. The real problem is the air pockets. This one doesn't seem so bad though, I think I remember solving a similar problem in a job interview ages ago, where I had to figure out how may 'blobs' were in a 2d array. This is functionally the same.

I'm making the assumption 0,0,0 is going to be the 'outside' air, so:

  • Cache every empty space that is that, or adjacent to an 'outside' space. Simple breadth first search.
  • Go through array again, and 'fill' every 'empty' space that is not in the outside space
  • Calculate surface area

I don't even have to change any of my original code, just add an extra processing pass.

#define COORD tuple<int, int, int>

set<COORD> outside;
queue<COORD> outCheck;

// Cache 'outside' spaces
outCheck.push(COORD(0, 0, 0));
while (!outCheck.empty())
{
    auto c = outCheck.front(); outCheck.pop();
    if (!outside.insert(c).second) continue;

    int x = get<0>(c), y = get<1>(c), z = get<2>(c);

    if (x+1 < DROP_SIZE && !drop[x+1][y][z]) outCheck.push(COORD(x+1, y, z));
    if (x   > 0         && !drop[x-1][y][z]) outCheck.push(COORD(x-1, y, z));
    if (y+1 < DROP_SIZE && !drop[x][y+1][z]) outCheck.push(COORD(x, y+1, z));
    if (y   > 0         && !drop[x][y-1][z]) outCheck.push(COORD(x, y-1, z));
    if (z+1 < DROP_SIZE && !drop[x][y][z+1]) outCheck.push(COORD(x, y, z+1));
    if (z   > 0         && !drop[x][y][z-1]) outCheck.push(COORD(x, y, z-1));
}

// Fill in air pockets
for (int x = 0; x < DROP_SIZE; x++)
for (int y = 0; y < DROP_SIZE; y++)
for (int z = 0; z < DROP_SIZE; z++)
{
    if (drop[x][y][z]) continue;
    if (outside.find(COORD(x, y, z)) != outside.end()) continue;

    drop[x][y][z] = true;
}

And that really was it. Huh. That was easy, and kind a fun.

Also look, somebody 3d printed their input!


Time taken: 40 minutes

My solutions for today's puzzles