Update day17.py

This commit is contained in:
kamoshi 2020-12-17 16:07:41 +01:00 committed by GitHub
parent 6d973c7579
commit 139ade1672
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,4 +1,13 @@
def parse_data() -> list[list[bool]]:
input_data = []
with open("input.txt") as file:
for line in file:
input_data.append([True if x == '#' else False for x in line.rstrip()])
return input_data
class Space:
def __init__(self, row: int, col: int, height: int):
self.space: list[list[list[bool]]] = []
@ -93,31 +102,152 @@ class Space:
print(''.join(['#' if x else '.' for x in row]))
def parse_data() -> list[list[bool]]:
input_data = []
with open("input.txt") as file:
for line in file:
input_data.append([True if x == '#' else False for x in line.rstrip()])
class Space4D:
def __init__(self, row: int, col: int, height: int, w_dim: int):
self.space: list[list[list[list[bool]]]] = []
self.row = row
self.col = col
self.height = height
self.w_dim = w_dim
self._offset_row = 0
self._offset_col = 0
self._offset_h = 0
self._offset_w = 0
return input_data
for h in range(self.height):
level_l = []
for row in range(self.row):
row_l = []
for col in range(self.col):
w_dim_l = []
for w in range(self.w_dim):
w_dim_l.append(False)
row_l.append(w_dim_l)
level_l.append(row_l)
self.space.append(level_l)
# Loads data with a given offset
def load_data(self, data: list[list[bool]], offset_row: int, offset_col: int, offset_h: int, offset_w: int) -> None:
self._offset_row = offset_row
self._offset_col = offset_col
self._offset_h = offset_h
self._offset_w = offset_w
def generate_space(data: list[list[bool]], max_turns: int) -> 'Space':
size_row = len(data[0]) + (max_turns * 2)
size_col = len(data) + (max_turns * 2)
space: Space = Space(row=size_row, col=size_col, height=(max_turns * 2) + 1)
space.load_data(data=data, offset_col=max_turns, offset_row=max_turns, offset_h=max_turns)
return space
for row in range(self._offset_row, len(data) + self._offset_row):
for col in range(self._offset_col, len(data[0]) + self._offset_col):
self.space[self._offset_h][row][col][self._offset_w] = data[row-self._offset_row][col-self._offset_col]
# Get activation value from absolute x,y,z, False if outside bounds
def get(self, row: int, col: int, h: int, w_dim: int) -> bool:
if 0 <= h < self.height and 0 <= row < self.row and 0 <= col < self.col and 0 <= w_dim < self.w_dim:
return self.space[h][row][col][w_dim]
return False
# Set activation value for absolute x,y,z, crash if outside bounds
def set(self, row: int, col: int, h: int, w_dim: int, value: bool) -> None:
self.space[h][row][col][w_dim] = value
# Get activation value from offset x,y,z, False if outside bounds
def get_o(self, row: int, col: int, h: int, w_dim: int):
return self.get(row+self._offset_row, col+self._offset_col, h+self._offset_h, w_dim+self._offset_w)
# Set activation value for offset x,y,z, crash if outside bounds
def set_o(self, row: int, col: int, h: int, w_dim: int, value: bool) -> None:
self.set(row+self._offset_row, col+self._offset_col, h+self._offset_h, w_dim+self._offset_w, value)
# Counts activated neighbours for a given absolute position
def count_neighbours(self, row: int, col: int, h: int, w_dim: int) -> int:
checked = [(-1,-1,-1,-1),(-1,-1,-1,0),(-1,-1,-1,1),(-1,-1,0,-1),(-1,-1,0,0),(-1,-1,0,1),(-1,-1,1,-1),
(-1,-1,1,0),(-1,-1,1,1),(-1,0,-1,-1),(-1,0,-1,0),(-1,0,-1,1),(-1,0,0,-1),(-1,0,0,0),
(-1,0,0,1),(-1,0,1,-1),(-1,0,1,0),(-1,0,1,1),(-1,1,-1,-1),(-1,1,-1,0),(-1,1,-1,1),(-1,1,0,-1),
(-1,1,0,0),(-1,1,0,1),(-1,1,1,-1),(-1,1,1,0),(-1,1,1,1),(0,-1,-1,-1),(0,-1,-1,0),(0,-1,-1,1),
(0,-1,0,-1),(0,-1,0,0),(0,-1,0,1),(0,-1,1,-1),(0,-1,1,0),(0,-1,1,1),(0,0,-1,-1),(0,0,-1,0),
(0,0,-1,1),(0,0,0,-1),(0,0,0,1),(0,0,1,-1),(0,0,1,0),(0,0,1,1),(0,1,-1,-1),(0,1,-1,0),
(0,1,-1,1),(0,1,0,-1),(0,1,0,0),(0,1,0,1),(0,1,1,-1),(0,1,1,0),(0,1,1,1),(1,-1,-1,-1),
(1,-1,-1,0),(1,-1,-1,1),(1,-1,0,-1),(1,-1,0,0),(1,-1,0,1),(1,-1,1,-1),(1,-1,1,0),(1,-1,1,1),
(1,0,-1,-1),(1,0,-1,0),(1,0,-1,1),(1,0,0,-1),(1,0,0,0),(1,0,0,1),(1,0,1,-1),(1,0,1,0),(1,0,1,1),
(1,1,-1,-1),(1,1,-1,0),(1,1,-1,1),(1,1,0,-1),(1,1,0,0),(1,1,0,1),(1,1,1,-1),(1,1,1,0),(1,1,1,1)]
count = 0
for col_o, row_o, h_o, w_o in checked:
if self.get(row=row+row_o, col=col+col_o, h=h+h_o, w_dim=w_dim+w_o):
count += 1
return count
# Counts activated neighbours for a given offset position
def count_neighbours_o(self, row: int, col: int, h: int, w_dim: int) -> int:
return self.count_neighbours(row+self._offset_row, col+self._offset_col, h+self._offset_h, w_dim+self._offset_w)
# Get the next state of the space
def next(self) -> 'Space4D':
next_space: Space4D = Space4D(self.col, self.row, self.row, self.w_dim)
for h in range(self.height):
for r in range(self.row):
for c in range(self.col):
for w in range(self.w_dim):
active_ns = self.count_neighbours(r, c, h, w)
active = self.get(r, c, h, w)
if active:
next_space.set(r, c, h, w, active_ns in [2, 3])
else:
next_space.set(r, c, h, w, active_ns == 3)
return next_space
# Count all activated values
def count_activated(self) -> int:
counted = 0
for level in self.space:
for column in level:
for w_dim in column:
counted += sum(w_dim)
return counted
# Print at level
def print_level(self, level: int, w_level: int):
level_grid = self.space[level]
for row in level_grid:
print(''.join(['#' if x[w_level] else '.' for x in row]))
def solve_p1(data: list[list[bool]]) -> int:
def generate_space(_data: list[list[bool]], max_turns: int) -> Space:
size_row = len(data[0]) + (max_turns * 2)
size_col = len(data) + (max_turns * 2)
_space: Space = Space(row=size_row, col=size_col, height=(max_turns * 2) + 1)
_space.load_data(data=data, offset_col=max_turns, offset_row=max_turns, offset_h=max_turns)
return _space
turns = 6
space: Space = generate_space(data, max_turns=turns)
for i in range(turns):
space = space.next()
return space.count_activated()
def solve_p2(data: list[list[bool]]) -> int:
def generate_space_4d(_data: list[list[bool]], max_turns: int) -> Space4D:
size_row = len(data[0]) + (max_turns * 2)
size_col = len(data) + (max_turns * 2)
_space: Space4D = Space4D(row=size_row, col=size_col, height=(max_turns * 2) + 1, w_dim=(max_turns * 2) + 1)
_space.load_data(data=data, offset_col=max_turns, offset_row=max_turns, offset_h=max_turns, offset_w=max_turns)
return _space
turns = 6
space: Space4D = generate_space_4d(data, turns)
for i in range(turns):
space = space.next()
return space.count_activated()
DATA = parse_data()
print(solve_p1(DATA))
print(solve_p2(DATA))