···11+import fileinput
22+from utils import Point
33+44+55+def solve_part_1(board):
66+ def serialize(board):
77+ res = ''
88+ for y in range(5):
99+ res += ''.join(board[Point(x, y)] for x in range(5))
1010+ return res
1111+1212+ def diversity_score(board):
1313+ return sum(2 ** i if c == '#' else 0 for i, c in enumerate(serialize(board)))
1414+1515+ seen = set()
1616+1717+ while True:
1818+ new_board = {}
1919+ for p in board:
2020+ count = 0
2121+ for np in p.neighbours_4():
2222+ if board.get(np, '.') == '#':
2323+ count += 1
2424+2525+ if board.get(p, '.') == '#':
2626+ new_board[p] = '#' if count == 1 else '.'
2727+ else:
2828+ new_board[p] = '#' if count == 1 or count == 2 else '.'
2929+3030+ if serialize(new_board) in seen:
3131+ return diversity_score(new_board)
3232+3333+ seen.add(serialize(new_board))
3434+ board = new_board
3535+3636+3737+def solve_part_2(board):
3838+ def recursive_neighbours(x, y, z):
3939+ for np in Point(x, y).neighbours_4():
4040+ if np.x == 2 and np.y == 2:
4141+ for i in range(5):
4242+ if x == 1:
4343+ yield (0, i, z + 1)
4444+ elif x == 3:
4545+ yield (4, i, z + 1)
4646+ elif y == 1:
4747+ yield (i, 0, z + 1)
4848+ elif y == 3:
4949+ yield (i, 4, z + 1)
5050+ elif np.x == -1:
5151+ yield (1, 2, z - 1)
5252+ elif np.x == 5:
5353+ yield (3, 2, z - 1)
5454+ elif np.y == -1:
5555+ yield (2, 1, z - 1)
5656+ elif np.y == 5:
5757+ yield (2, 3, z - 1)
5858+ else:
5959+ yield (np.x, np.y, z)
6060+6161+6262+ for minutes in range(200):
6363+ new_board = {}
6464+6565+ for z in range(-201, 201):
6666+ for y in range(5):
6767+ for x in range(5):
6868+ if x == 2 and y == 2:
6969+ continue
7070+7171+ count = 0
7272+ for nx, ny, nz in recursive_neighbours(x, y, z):
7373+ if board.get((nx, ny, nz), '.') == '#':
7474+ count += 1
7575+7676+ if board.get((x, y, z), '.') == '#':
7777+ new_board[(x, y, z)] = '#' if count == 1 else '.'
7878+ else:
7979+ new_board[(x, y, z)] = '#' if count == 1 or count == 2 else '.'
8080+8181+ board = new_board
8282+8383+ return board.values().count('#')
8484+8585+8686+# Read problem input
8787+PART_1 = {}
8888+PART_2 = {}
8989+9090+for y, line in enumerate(fileinput.input()):
9191+ for x, c in enumerate(line.strip()):
9292+ PART_1[Point(x, y)] = c
9393+ if not (x == 2 and y == 2):
9494+ PART_2[(x, y, 0)] = c
9595+9696+print "Biodiversity rating for first repeated layout:", solve_part_1(PART_1)
9797+print "Bugs in recursive space after 200 minutes:", solve_part_2(PART_2)