1
0

Solved part 2 of day 17.This solution works for any n dimensions.

This commit is contained in:
Rokas Puzonas 2020-12-18 19:46:23 +02:00
parent 1c5c41a13a
commit d4ccbc25c9

View File

@ -1,12 +1,56 @@
import time import time
from itertools import permutations
neighbourOffsets = set() # This is really waaayy over-engineered :D
for x in range(-1, 2): # It's just wanted to try this out, so it would work
for y in range(-1, 2): # for any N dimensions
for z in range(-1, 2): # For this reason it is also a bit slower in general
neighbourOffsets.add((x, y, z)) class ConwayCubes:
neighbourOffsets.remove((0, 0, 0)) def __init__(self, initialState, dimensions=3):
self.neighbourOffsets = set(permutations((-1, 0, 1) * dimensions, dimensions))
self.neighbourOffsets.remove((0,) * dimensions)
self.dimensions = dimensions
self.state = set()
for cube in initialState:
missingDimensions = dimensions-len(cube)
if missingDimensions < 0: # Some dimensions need to be removed
self.state.add(cube[:dimensions])
else:
self.state.add(cube + (0,) * missingDimensions)
@staticmethod
def addTuples(t1, t2):
return tuple(sum(x) for x in zip(t1, t2))
def getNeighbourCount(self, cube):
count = 0
for offset in self.neighbourOffsets:
neighbour = ConwayCubes.addTuples(cube, offset)
if neighbour in self.state:
count += 1
return count
def simulateCycle(self):
nextState = set()
toBeComputedCubes = set()
for activeCube in self.state:
toBeComputedCubes.add(activeCube)
for offset in self.neighbourOffsets:
neighbour = ConwayCubes.addTuples(activeCube, offset)
toBeComputedCubes.add(neighbour)
for cube in toBeComputedCubes:
neighbourCount = self.getNeighbourCount(cube)
if (cube in self.state and 2 <= neighbourCount <= 3) or neighbourCount == 3:
nextState.add(cube)
self.state = nextState
def simulateCycles(self, n=1):
for i in range(n):
self.simulateCycle()
def getInitialState(filename): def getInitialState(filename):
initialState = set() initialState = set()
@ -16,55 +60,10 @@ def getInitialState(filename):
for y in range(len(lines)): for y in range(len(lines)):
for x in range(len(lines[y])): for x in range(len(lines[y])):
if lines[y][x] == '#': if lines[y][x] == '#':
initialState.add((x, y, 0)) initialState.add((x, y))
return initialState return initialState
def getNeighbourCount(state, spot):
count = 0
for offset in neighbourOffsets:
neighbour = (
spot[0] + offset[0],
spot[1] + offset[1],
spot[2] + offset[2]
)
if neighbour in state:
count += 1
return count
def isNextCubeStateActive(state, spot):
neighbourCount = getNeighbourCount(state, spot)
if spot in state:
return neighbourCount == 3 or neighbourCount == 2
elif neighbourCount == 3:
return True
else:
return False
def simulateNextState(state):
nextState = set()
computedSpots = set()
for activeSpot in state:
if activeSpot not in computedSpots:
computedSpots.add(activeSpot)
if isNextCubeStateActive(state, activeSpot):
nextState.add(activeSpot)
for offset in neighbourOffsets:
neighbourSpot = (
activeSpot[0] + offset[0],
activeSpot[1] + offset[1],
activeSpot[2] + offset[2]
)
if neighbourSpot not in computedSpots:
computedSpots.add(neighbourSpot)
if isNextCubeStateActive(state, neighbourSpot):
nextState.add(neighbourSpot)
return nextState
def vizualizeState(state): def vizualizeState(state):
xLayers = set(spot[0] for spot in state) xLayers = set(spot[0] for spot in state)
yLayers = set(spot[1] for spot in state) yLayers = set(spot[1] for spot in state)
@ -78,21 +77,20 @@ def vizualizeState(state):
print("".join('#' if (x, y, z) in state else '.' for x in range(xMin, xMax+1))) print("".join('#' if (x, y, z) in state else '.' for x in range(xMin, xMax+1)))
print() print()
def simulateCycles(initialState, count=1):
state = initialState
for _ in range(6):
state = simulateNextState(state)
return state
def part1(intialState): def part1(intialState):
return len(simulateCycles(initialState, 6)) cubes = ConwayCubes(initialState, 3)
cubes.simulateCycles(6)
return len(cubes.state)
def part2(intialState): def part2(intialState):
pass cubes = ConwayCubes(initialState, 4)
cubes.simulateCycles(6)
return len(cubes.state)
if __name__ == "__main__": if __name__ == "__main__":
initialState = getInitialState("input.txt") initialState = getInitialState("input.txt")
start = time.perf_counter() start = time.perf_counter()
print("Part 1: ", part1(initialState)) print("Part 1: ", part1(initialState))
print("Part 2: ", part2(initialState))
end = time.perf_counter() end = time.perf_counter()
print("Runtime {:.3f}".format(end-start)) print("Runtime {:.3f}".format(end-start))