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')

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 putting `e` and `w` last they won’t be included from the `ne` or `sw` instances.
• Then we set up `x` and `y` 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 the `x` and `y` vars accordingly.
• After it loops through all of the directions my `x` and `y` 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 to `expandTiles`.
• Then we find the x y for this tile
• Then loop through all the `neighborPositions` and find each neighbor using `getXYfromDir`.
• If this neighbor does not exist in `tiles` we add it to `expandTiles`
• 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)

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 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 from `expandTiles`
• 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.