## Advent of Code 2023 Day 21

### Part 1

#### I hope it's as easy as I think

- 64 steps
- Even number steps
- Any tile that can be reached in 64 or fewer steps
- And an amount of steps that is even
- Is a valid tile

I plan to write a recursive function that:

- Continually walks away from the starting point
- Catalogues each tile visited
- Adds tiles visited on every other step to a list of valid tiles
- Avoids proceeding if a tile has been visited

This has worked for similar challenges.

I expect it to work here.

But I've been surprised before!

Here I go!

#### Make grid; Find start; Prepare grid;

Make grid:

```
input.split('\n').map(line => line.split(''))
```

Find start:

- Luckily, the start is dead-center of a grid with equal and odd length dimensions
- So, the start is at X and Y of
`(length - 1) / 2`

```
let start = [(grid.length - 1) / 2, (grid.length - 1) / 2]
```

Prepare grid:

```
grid[start[0]][start[1]] = '.'
```

#### That same list of adjacent tiles

Remember this?

```
const adjacents = [[-1,0],[0,1],[1,0],[0,-1]]
```

I'll use that in my recursive function to check all four possible next moves at the current tile.

#### Writing my recursive function

Here it is:

```
function stepper(current, steps) {
if (steps > 64) return false;
visited.add(current.join(','))
if (steps % 2 == 0) {
valid.add(current.join(','))
}
adjacents.forEach(coord => {
let [row, col] = [current[0] + coord[0], current[1] + coord[1]]
if (row < 0 || row == grid.length || col < 0 || col == grid[0].length) {
return false;
} else {
switch (grid[row][col]) {
case '#':
visited.add(row + ',' + col)
return;
case '.':
return stepper([row,col], steps + 1)
}
}
})
}
```

It runs. But it doesn't finish when run on my example input.

For the same reason as a few days ago: too many rabbit holes to dig and climb out of.

So, I need to write a non-recursive function.

One that visits all the tiles within a 64 step radius.

And just accumulates tiles to proceed from along it's journey.

#### Writing my non-recursive function

"This will be straightforward", I thought.

"I did this recently, so it's just recall", I thought.

"Should only take a few minutes to code up", I thought.

Fast-forward an hour.

"Why is my list of cells to visit getting higher than the amount of cells in my grid?", I thought.

"Why are there multiple occurrences of the same cell with the same step count?", I thought.

"Why isn't this working?", I thought.

Fast-forward a half hour.

I figured out my error.

It was simple:

In my `case`

for the next cell being a `.`

, I first check whether that cell has been visited. If it hasn't, I add it to my list of cells to visit.

What I was missing was adding it to the list of visited cells, since I know I'm eventually going to visit it.

Here's my entire program in JavaScript:

```
let grid = input.split('\n').map(line => line.split(''))
let start = [(grid.length - 1) / 2, (grid.length - 1) / 2]
grid[start[0]][start[1]] = '.'
const adjacents = [[-1,0],[0,1],[1,0],[0,-1]]
let visited = new Set()
visited.add(start.join(','))
let valid = new Set()
let todo = [[start, 0]]
while (todo.length > 0) {
let [xy, steps] = todo.shift()
let [row, col] = xy
if (steps % 2 == 0 && steps <= 64) {
valid.add(xy.join(','))
}
adjacents.forEach(coord => {
let [r, c] = [row + coord[0], col + coord[1]]
if (r < 0 || r >= grid.length || c < 0 || c >= grid[0].length) {
return false;
} else {
switch (grid[r][c]) {
case '#':
visited.add(r + ',' + c)
break;
case '.':
if (!visited.has([r,c].join(','))) {
visited.add(r + ',' + c)
todo.push([[r,c], steps + 1])
}
break;
}
}
})
}
```

#### Running my program with fingers crossed

It generates `42`

on the example input.

There are 80 `.`

s in the example input, not including the `S`

.

And since the even step rule is in effect, that feels like the correct answer: half the total `.`

s.

Running it on my puzzle input only took a few seconds to complete.

It generated a number just under 4k.

It is the correct answer!

Woohoo!!!

That wasn't as easy as I'd hoped. Mostly due to my ignorance.

But I got there.

### Part 2

#### To infinity, and...no thanks.

I love the twist:

- Infinite repeating grid
- A step count in the tens of millions

I know for sure I couldn't solve this by simulating single-cell movements.

I have a hunch there's a neat formula that correlates the area of the circle surrounding the starting point with the number of possible valid steps.

Except, in my input I see instances of this pattern:

```
.#.
#.#
.#.
```

That middle cell is unreachable, and should never be counted in such a formula.

So, now I'm really at a loss for how I'd solve this.

Sadly, I know I won't be earning another gold star today.

I'll gladly take my one gold star with me to the next challenge.

And hope that I can solve at least two more Part 1's before this year is over.

I have four more chances!

## Top comments (0)