- Advent of Code is over, here’s what I thought
- Advent of Code, Day 25
- Advent of Code, Day 24 – Black Lives Matter
- Advent of Code, Day 23
- Advent of Code, Day 22
Day 24 of Advent of Code is here!
Black Lives Matter
Today’s puzzle uses two color options, black and white. And as we step through the rules we are changing tiles from black to white, and visa-versa. At some point I need to find how many black neighbors a tile has and change it based on that count. This felt all too real, and insensitive. I did not want to work with these color choices and terms. Instead, I completed it by using green and red instead. It’s Christmas time! Let’s stick with Christmas colors ;)
Black Lives Matter every day, not just when our news media says it does.
Day 24: Lobby Layout
Part I
Thankfully we’re not playing the crab anymore. Now we’re in a lobby of a resort. The floor is being renovated with hexagon (6 sided) tiles are being put down. Using some directional instructions, we can determine which tiles should be red and which should be green.
I had to draw this out, as a 6 sided shape is not something we normally work with. The above coords are e for east, ne for northeast and so on…

Then I created my coordinate system so x and y would be the middle of a hexagon, like

If we were to go east
we would move x up (right) two. Going north
would move y up one. Going north east
would add one to both x and y.
Now let’s see about some data. They didn’t make it easy:

Let’s get the data
const fs = require('fs')
let data = fs.readFileSync('./input.txt', 'utf-8').trim().split('\n')
const tiles = new Map()
let greenCounter = 0
Yup, the same method to get the data as normal. I created a new Map called tiles
to store each tile we create, so we can track whether they’re green or red.
Now lets loop through the data
data.forEach(row => {
const directions = row.match(/(se)|(ne)|(sw)|(nw)|(e)|(w)/g)
let x = 0
let y = 0
directions.forEach(dir => {
switch(dir) {
case 'e':
x += 2
break
case 'w':
x -= 2
break
case 'se':
x += 1
y -= 1
break
case 'sw':
x -= 1
y -= 1
break
case 'ne':
x += 1
y += 1
break
case 'nw':
x -= 1
y += 1
break
default:
break
}
})
const theTile = `x${x}y${y}`;
if(tiles.get(theTile)) {
tiles.set(theTile, 'red')
greenCounter -= 1
} else {
tiles.set(theTile, 'green')
greenCounter += 1
}
})
- First let’s get the directions. These long strings of undelimited directions was intimidating at first, but regex to the rescue! This little regex ensures we will get each coordinate, in their right order
(se)|(ne)|(sw)|(nw)|(e)|(w)
– just looks for those specific characters and returns them. Regex executes in order, by puttinge
andw
last they won’t be included from thene
orsw
instances.
- Then we set up
x
andy
vars to store the movement as we go. - Now let’s loop through the directions for the current row.
- I use a switch() off of the
dir
ection, and set thex
andy
vars accordingly. - After it loops through all of the directions my
x
andy
will be the tile we end on. - I create a unique string containing the coordinates.
- To ensure it’s unique, I added x and y as values in there. And sort of delimiter would work. If I didn’t, I couldn’t guarantee the values would be unique. If x is 11 and y is 4, and I just concatenated those, the value would be 114. That could also match x 1 y 14.
- Next we check if the
tiles
Map() has this value already. If it does, we change its color to red. - If we don’t have this tile already, it defaults to green.
- You’ll also notice a little
greenCounter
which collects our answer.
To get the final answer, we just write it out
console.log('There are', greenCounter, 'green tiles')
Part II
No, no crazy “now do this a gazillion times” this day. Instead, we add some new rules and run through it a few more times. Based on the number of neighbors of a color, a tile can change colors. We will then run through this 100 times.
Most of part 1 lives on here, with some refactoring:
const getXYfromDir = (x, y, direction) => {
let xx = x
let yy = y
switch(direction) {
case 'e':
xx += 2
break
case 'w':
xx -= 2
break
case 'se':
xx += 1
yy -= 1
break
case 'sw':
xx -= 1
yy -= 1
break
case 'ne':
xx += 1
yy += 1
break
case 'nw':
xx -= 1
yy += 1
break
default:
break
}
return { x: xx, y: yy }
}
I ripped out the above from part 1 and created its own function. This will be used a few times.
data.forEach(row => {
const directions = row.match(/(se)|(ne)|(sw)|(nw)|(e)|(w)/g)
let x = 0
let y = 0
directions.forEach(dir => {
const newCoords = getXYfromDir(x, y, dir)
x = newCoords.x
y = newCoords.y
})
const theTile = `x${x}y${y}`;
if(tiles.get(theTile)) {
tiles.set(theTile, 'red')
greenCounter -= 1
} else {
tiles.set(theTile, 'green')
greenCounter += 1
}
})
This is also from part 1, now refactored to use the getXYfromDir
function.
Now we get looping, 100 times.
const neighborPositions = ['e', 'w', 'se', 'sw', 'ne', 'nw']
Before that, let’s define all the neighbors
for(let loop = 0; loop < 100; loop += 1) {
greenCounter = 0
const expandTiles = new Map()
Using a for() loop, I reset some variables on each loop. More to come on these
tiles.forEach((value, key) => {
expandTiles.set(key, value)
const [str, x, y] = key.match(/x([\-0-9]*)y([\-0-9]*)/)
neighborPositions.forEach(dir => {
const neigh = getXYfromDir(Number(x), Number(y), dir)
const theTile = `x${neigh.x}y${neigh.y}`;
if(!tiles.get(theTile)) expandTiles.set(theTile, 'red')
})
})
Here we expand our current tiles to include new neighbors.
- As we loop through the
tiles
, we’re adding those tiles toexpandTiles
. - Then we find the x y for this tile
- Then loop through all the
neighborPositions
and find each neighbor usinggetXYfromDir
. - If this neighbor does not exist in
tiles
we add it toexpandTiles
- This will be the last we use
tiles
in this loop, until we set it to a new object at the end. - We can’t just add new neighbors to
tiles
as that would loop indefinitely (yes, I learned that by doing that)
- This will be the last we use
Once we have the new set of tiles expandTiles
, we loop through and flip their colors
const nextDayTiles = new Map()
expandTiles.forEach((value, key) => {
const numGreenNeighbors = getNeighborCount(key)
if(value === 'green') {
if(numGreenNeighbors === 0 || numGreenNeighbors > 2) {
nextDayTiles.set(key, 'red')
} else {
greenCounter += 1
nextDayTiles.set(key, value)
}
} else if(value === 'red') {
if(numGreenNeighbors === 2) {
nextDayTiles.set(key, 'green')
greenCounter += 1
} else {
nextDayTiles.set(key, value)
}
}
})
- I create a new
nextDayTiles
Map() to store the tiles as we swap them. - Next we loop through all of the
expandTiles
- We find the number of neighbors that are green (
getNeighborCount
is below) - If the current tile is green
- If the neighbor count matches the criteria, this tile is now red and added to
nextDayTiles
- Otherwise, just add the tile to
nextDayTiles
- If the neighbor count matches the criteria, this tile is now red and added to
- If the current tile is red
- If the neighbor count matches the criteria, this tile is now green and added
- Otherwise, we just add this tile
At the end, nextDayTiles
, is loaded up with all tiles for the day, and the current colors.
const getNeighborCount = (tile) => {
const [str, x, y] = tile.match(/x([\-0-9]*)y([\-0-9]*)/)
let greenCount = 0
neighborPositions.forEach(dir => {
const neigh = getXYfromDir(Number(x), Number(y), dir)
const theTile = `x${neigh.x}y${neigh.y}`;
if(expandTiles.get(theTile)) {
if(expandTiles.get(theTile) === 'green') greenCount += 1
}
})
return greenCount
}
I am getting the neighbor count in getNeighborCount
- We grab the current x y coordinates of the tile
- Then we loop through all of the
neighborPositions
, getting each of their x y and getting their value fromexpandTiles
- Then we return the number of green
tiles = nextDayTiles
console.log('Day', loop + 1, 'There are', greenCounter, 'green tiles')
}
Finally, at the bottom of the loop, I set tiles
to nextDayTiles
and print out how many green there are for this day. When the code finishes, it’ll show Day 100’s answer
How did it go for you?
How did you find the answer on your own? How did you do it? Anything stump you? I’d love to hear how you did! Please comment below! I have also loaded up just the challenge and code from this and my other days on github, you can follow along there too: pretty Git pages or the code in the repo.