Advent of Code day 17

Time to do some catchup.

As I mentioned in my earlier post the Day 17 puzzle Conway Cubes is superficially similar to Day 11 Seating System which I wrote about here.

The pocket dimension contains an infinite 3-dimensional grid. At every integer 3-dimensional coordinate (x,y,z), there exists a single cube which is either active or inactive.

In the initial state of the pocket dimension, almost all cubes start inactive. The only exception to this is a small flat region of cubes (your puzzle input); the cubes in this region start in the specified active (#) or inactive (.) state.

The energy source then proceeds to boot up by executing six cycles.

Each cube only ever considers its neighbors: any of the 26 other cubes where any of their coordinates differ by at most 1. For example, given the cube at x=1,y=2,z=3, its neighbors include the cube at x=2,y=2,z=2, the cube at x=0,y=2,z=3, and so on.

During a cycle, all cubes simultaneously change their state according to the following rules:

If a cube is active and exactly 2 or 3 of its neighbors are also active, the cube remains active. Otherwise, the cube becomes inactive. If a cube is inactive but exactly 3 of its neighbors are active, the cube becomes active. Otherwise, the cube remains inactive.

This all seems complicated, but really it's just the seating problem in in 3D. I started with the code I had on day 11 and adjusted it. We start with a 2D array that's quite similar to the day 11 input. To make the transition to 3D, at the end of my create_array function I return

np.expand_dims(new_plan, axis=0)

The expand_dims is a way of adding a dimension to an np array. I spent some time trying to do it manually using lists of lists before converting to an np array, but this turned out to the be easy solution.

After that it was really just an exercise in chasing down dimensions and errors -- lots of print statements and working through the example problem to really track what the code was doing. I found that I needed to pad my np array by 2 since this solution space can grow. But increasing the solution space by 4 rows in every dimension each cycle is not sustainable, so I wrote a trim_edges routine to run at the end of each cycle and remove rows of all zeros. At the end this wasn't a hard problem, it just took a bit of work to get it running smoothly.

Part 2 was the same problem, now in 4D. I replicated my code in 4D and it worked without much adjustment. 2 more stars down.