Advent of Code 2020 day 17
I spent ages trying to create a 3-dimension array for part 1 but gave up and went for a dictionary approach instead with nasty looking keys. Should have used tuples for the keys. It turns out that using a dict helped for part two anyway.
My solutions to the challenges are getting less-and-less production-quality as the days go on…
Here’s my solution for part two: part one was the same just without the ‘w’ dimension.
import re
class Cube4D(object):
def __init__(self, raw_input):
self.cube = {
f'x{xi}y{yi}z0w0': x
for yi, y in enumerate(raw_input.strip().splitlines())
for xi, x in enumerate(y.strip())
}
def all_neighbours(self, c):
x0, y0, z0, w0 = [int(i) for i in re.match(r'^x(-*\d+)y(-*\d+)z(-*\d+)w(-*\d+)$', c).groups()]
return [
self.cube.get(f'x{x}y{y}z{z}w{w}', '.')
for w in range(w0-1, w0+2)
for z in range(z0-1, z0+2)
for y in range(y0-1, y0+2)
for x in range(x0-1, x0+2)
if (z, y, x, w) != (z0, y0, x0, w0)
]
def count_active_neighbours(self, c):
return len([ n for n in self.all_neighbours(c) if n == '#' ])
def count_all_active(self):
return len([ c for c in self.cube.values() if c == '#' ])
def get_new_state(self, c):
if self.cube.get(c, '.') == '#':
if self.count_active_neighbours(c) in [2, 3]:
return '#'
else:
return '.'
elif self.cube.get(c, '.') == '.' and self.count_active_neighbours(c) == 3:
return '#'
else:
return '.'
def edges(self):
xs = [ int(re.search(r'x(-*\d+)', c).group(1)) for c in self.cube.keys() ]
ys = [ int(re.search(r'y(-*\d+)', c).group(1)) for c in self.cube.keys() ]
zs = [ int(re.search(r'z(-*\d+)', c).group(1)) for c in self.cube.keys() ]
ws = [ int(re.search(r'w(-*\d+)', c).group(1)) for c in self.cube.keys() ]
return min(xs), max(xs), min(ys), max(ys), min(zs), max(zs), min(ws), max(ws)
def cycle(self):
new_cube = {}
xmin, xmax, ymin, ymax, zmin, zmax, wmin, wmax = self.edges()
for x in range(xmin-1, xmax+2):
for y in range(ymin-1, ymax+2):
for z in range(zmin-1, zmax+2):
for w in range(wmin-1, wmax+2):
new_cube[f'x{x}y{y}z{z}w{w}'] = self.get_new_state(f'x{x}y{y}z{z}w{w}')
self.cube = new_cube
if __name__ == '__main__':
c = Cube4D(INPUT)
for _ in range(6):
c.cycle()
print(c.count_all_active())