#!/usr/bin/env python from aoc import get_input # AoC import re # regex import numpy as np from copy import deepcopy as copy config = get_input(17).strip().split("\n") for i in range(len(config)): newlst = [] newlst[:0] = config[i] config[i] = newlst initlen = len(config[0]) print("Config:") print(np.asarray(config)) cube = np.asarray([ np.zeros((initlen,initlen), int) for z in range(initlen) ]) cube4 = np.asarray([[ np.zeros((initlen,initlen), int) for z in range(initlen) ] for w in range(initlen) ]) #apply config to network cubelen = initlen cubelen4 = initlen cycles = 6 for iy in range(len(config)): for ix in range(len(config)): if(config[iy][ix] == "."): cube[1][iy][ix] = 0 else: cube[1][iy][ix] = 1 for iy, row in enumerate(config): for ix, node in enumerate(row): val = 0 if( node == "#" ): val = 1 cube4[1][1][iy][ix] = val print("Part 1: Cube shape:", cube.shape) print("Part 2: Hypercube shape:", cube4.shape) def getpos(x, y, z, net=cube): netlen = net.shape[0] if(x in range(netlen) and y in range(netlen) and z in range(netlen)): return net[z][y][x] else: return None def setpos(x, y, z, val, net=cube): netlen = net.shape[0] if( x in range(netlen) and y in range(netlen) and z in range(netlen) ): net[z][y][x] = val else: return None def countaround(x, y, z, net=cube): px = [-1, 0, 1] py = [-1, 0, 1] pz = [-1, 0, 1] around = dict() count = 0 checkcount = 0 for iz in pz: for iy in py: for ix in px: pos = (x+ix, y+iy, z+iz) if( pos != (x, y, z) ): checkcount += 1 val = getpos(pos[0], pos[1], pos[2], net) around[pos] = val if( val ): count += val return count, checkcount offset4 = set() for x in range(-1, 2): for y in range(-1, 2): for z in range(-1, 2): for w in range(-1, 2): if( (x, y, z, w) != (0, 0, 0, 0) ): offset4.add( (x, y, z, w) ) def getpos4(x, y, z, w, net=cube4): netlen = net.shape[0] if(x in range(netlen) and y in range(netlen) and z in range(netlen) and w in range(netlen)): return net[w][z][y][x] else: return None def setpos4(x, y, z, w, val, net=cube4): netlen = net.shape[0] if(x in range(netlen) and y in range(netlen) and z in range(netlen) and w in range(netlen)): net[w][z][y][x] = val def countaround4D(x, y, z, w, net=cube4): count = 0 checkcount = 0 for diff in offset4: val = getpos4(x+diff[0], y+diff[1], z+diff[2], w+diff[3], net) checkcount += 1 if( val == 1 ): count += 1 return count, checkcount def expandCube(net=cube, expand=1): net = np.pad(net, pad_width=expand, mode='constant', constant_values=0) cubelen = net.shape[0] return net, cubelen def runCycle(net, c=0, maxc=cycles, expand=False, ignoreCfgLayer=False): if( not c < maxc ): print("6 / 6 Done") return net if(expand): net, cubelen = expandCube(net, 1) newcube = net.copy() cubelen = net.shape[0] for iz in range(cubelen): if(iz == 1 and ignoreCfgLayer): continue for iy in range(cubelen): for ix in range(cubelen): node = getpos(ix, iy, iz, net) activeCount, checkdCount = countaround(ix, iy, iz, net) newnode = node if( node == 1 and not activeCount in [2, 3] ): newnode = 0 if( node == 0 and activeCount == 3 ): newnode = 1 setpos(ix, iy, iz, newnode, newcube) print( c, "/", maxc ) net = newcube return runCycle(net, c+1, expand=True, ignoreCfgLayer=ignoreCfgLayer) cycles = 6 def runCycle4(net, c=0, maxc=cycles, expand=False): if( not c < maxc ): print("6 / 6 Done") return net if(expand): net, cubelen = expandCube(net, 1) newcube = net.copy() cubelen4 = net.shape[0] for iw in range(cubelen4): for iz in range(cubelen4): for iy in range(cubelen4): for ix in range(cubelen4): node = getpos4(ix, iy, iz, iw, net) activeCount, checkdCount = countaround4D(ix, iy, iz, iw, net) newnode = node if( node == 1 and not activeCount in [2, 3] ): newnode = 0 if( node == 0 and activeCount == 3 ): newnode = 1 setpos4(ix, iy, iz, iw, newnode, newcube) print(c, "/", maxc) net = newcube return runCycle4(net, c+1, expand=True) # Part 1 print("\nPart 1...") cube, cubelen = expandCube(cube, 10) endcube = runCycle(cube) # Part 2 print("\nPart 2...") cube4, cubelen4 = expandCube(cube4, 2) endcube4 = runCycle4(cube4) print("Part1:", np.sum(endcube)) print("Part2:", np.sum(endcube4)) print("\nAt least it is faster than compiling Firefox Kappa")