diff --git a/2019/aoc2019/day24.py b/2019/aoc2019/day24.py index 9dced01..62cb729 100644 --- a/2019/aoc2019/day24.py +++ b/2019/aoc2019/day24.py @@ -1,4 +1,4 @@ -from typing import TextIO, Iterable, Tuple +from typing import TextIO, Iterable, Tuple, List def read_board(data: TextIO) -> Tuple[Tuple[bool]]: @@ -45,6 +45,77 @@ def advance_board(board: Tuple[Tuple[bool]]) -> Tuple[Tuple[bool]]: return tuple(create_row(y, row) for y, row in enumerate(board)) +def neighbours2(board: List[Tuple[Tuple[bool]]], x: int, y: int, z: int) -> int: + existing = range(len(board)) + + if z in existing: + # Normal board count, minus the middle tile if applicable + n = neighbours(board[z], x, y) - board[z][2][2] + else: + n = 0 + + if z - 1 in existing: + if y == 2: + if x == 1: + n += sum(board[z - 1][iy][0] for iy in range(5)) + elif x == 3: + n += sum(board[z - 1][iy][4] for iy in range(5)) + elif x == 2: + if y == 1: + n += sum(board[z - 1][0]) + elif y == 3: + n += sum(board[z - 1][4]) + + if z + 1 in existing: + if y == 0: + n += board[z + 1][1][2] + elif y == 4: + n += board[z + 1][3][2] + + if x == 0: + n += board[z + 1][2][1] + elif x == 4: + n += board[z + 1][2][3] + + return n + + +def advance_board2(board: List[Tuple[Tuple[bool]]]) -> List[Tuple[Tuple[bool]]]: + layers = [] + + for z in range(-1, len(board) + 1): + layer = [] + + for y in range(5): + row = [] + + for x in range(5): + if y == 2 and x == 2: + row.append(False) + continue + + if z in range(len(board)): + live = board[z][y][x] + else: + live = False + + if live: + row.append(neighbours2(board, x, y, z) == 1) + else: + row.append(neighbours2(board, x, y, z) in [1, 2]) + + layer.append(tuple(row)) + + layers.append(tuple(layer)) + + if sum(flatten(layers[0])) == 0: + layers = layers[1:] + if sum(flatten(layers[-1])) == 0: + layers = layers[:-1] + + return layers + + def part1(data: TextIO) -> int: board = read_board(data) @@ -56,3 +127,12 @@ def part1(data: TextIO) -> int: return sum(2 ** i for i, b in enumerate(flatten(board)) if b) seen.add(board) + + +def part2(data: TextIO, rounds: int = 200) -> int: + board = [read_board(data)] + + for _ in range(rounds): + board = advance_board2(board) + + return sum(flatten(flatten(board)))