import math data = open('input', 'r').readlines() data = [list(x.strip()) for x in data] def polarToXY(direction, distance): if direction % 2 == 1: distance *= math.sqrt(2) x = distance * math.cos(direction * math.pi / 4) y = distance * math.sin(direction * math.pi / 4) return [round(x), round(y)] def getTile(mat, x, y): if x < 0 or x >= len(mat): raise Exception('oob: x') if y < 0 or y >= len(mat[x]): raise Exception('oob: y') return mat[x][y] def neighbors(mat, x, y): neighbor_list = [] for direction in range(8): try: distance = 1 i, j = polarToXY(direction, distance) neighbor = getTile(mat, x + i, y + j) while neighbor == '.': distance += 1 i, j = polarToXY(direction, distance) neighbor = getTile(mat, x + i, y + j) neighbor_list.append(neighbor) except: pass return neighbor_list def serialize(mat): return '\n'.join([''.join(line) for line in mat]) def apply(mat): newData = [] for x, _ in enumerate(mat): line = [] for y, _ in enumerate(mat[x]): neigh = list(neighbors(mat, x, y)) if mat[x][y] == 'L' and '#' not in neigh: line.append('#') elif mat[x][y] == '#' and neigh.count('#') >= 5: line.append('L') else: line.append(mat[x][y]) newData.append(line) return newData prev = '' while serialize(data) != prev: prev = serialize(data) data = apply(data) print(prev.count('#'))