import itertools cycles = 6 initial_size = -1 max_size_xy = -1 max_size_zw = -1 def read_input_boxes(): global initial_size, max_size_xy, max_size_zw with open('day17/input') as reader: lines = reader.read().splitlines() initial_size = len(lines[0]) max_size_xy = initial_size + (cycles * 2) max_size_zw = ((cycles * 2)+1) initial_boxes = [[[[False for _ in range(max_size_zw)] for _ in range(max_size_zw)] for _ in range(max_size_xy)] for _ in range(max_size_xy)] for x in range(0, initial_size): for y in range(0, initial_size): initial_boxes[x + cycles][y+cycles][cycles][cycles] = lines[x][y] == '#' return initial_boxes def is_active(boxes, location): global initial_size, max_size_xy, max_size_zw if any([c < 0 for c in location]) or location[0]>=max_size_xy or location[1]>=max_size_xy or location[2]>=max_size_zw or location[3]>=max_size_zw: return 0 return 1 if boxes[location[0]][location[1]][location[2]][location[3]] else 0 def generate_all_neighbours(x, y, z, w): x_checks = [x, x - 1, x + 1] y_checks = [y, y - 1, y + 1] z_checks = [z, z - 1, z + 1] w_checks = [w, w - 1, w + 1] neighbours = list(itertools.product(x_checks, y_checks, z_checks, w_checks)) neighbours.remove((x, y, z, w)) return neighbours def check_state(boxes, previous_boxes, x, y, z, w): neighbours = generate_all_neighbours(x, y, z, w) active_neighbours = sum(map(lambda n: is_active(previous_boxes, n), neighbours)) if boxes[x][y][z][w]: boxes[x][y][z][w] = 2 <= active_neighbours <= 3 else: boxes[x][y][z][w] = active_neighbours == 3 boxes = read_input_boxes() for c in range(cycles): print("cycle: {}".format(c)) previous_boxes = [[[[boxes[x][y][z][w] for w in range(max_size_zw)] for z in range(max_size_zw)] for y in range(max_size_xy)] for x in range(max_size_xy)] for x in range(max_size_xy): for y in range(max_size_xy): for z in range(max_size_zw): for w in range(max_size_zw): check_state(boxes, previous_boxes, x, y, z, w) res = sum([sum([sum([sum(z) for z in y]) for y in x]) for x in boxes]) print(res)