2016-12-13 - A Maze of Twisty Little Cubicles
(original .ipynb)import math from advent import neighbours4 from heapq import heappush, heappop puzzle_input = 1358 test_input = 10 def tile_type(x, y, favourite_number): res = (x*x + 3*x + 2*x*y + y + y*y) + favourite_number return "." if sum(1 for c in bin(res) if c == '1') % 2 == 0 else "#" def build_grid(target_r, target_c, favourite_number): grid = [] r = 0 while r <= target_r: c = 0 row = [] while c <= target_c: row.append(tile_type(c, r, favourite_number)) c += 1 grid.append(row) r += 1 return grid def part_one(dest_c, dest_r, favourite_number): buffer = 5 grid = build_grid(dest_r + buffer, dest_c + buffer, favourite_number) distances = [ [ math.inf for c in range(dest_c + buffer + 1)] for r in range(dest_r + buffer + 1) ] queue = [] heappush(queue, (0, (1, 1))) while len(queue) > 0: steps, (r, c) = heappop(queue) if grid[r][c] == "#" or steps > distances[r][c]: continue if (r == dest_r) and (c == dest_c): return steps distances[r][c] = steps for (nr, nc) in neighbours4(grid, r, c): heappush(queue, (steps+1, (nr, nc))) return -1 assert 11 == part_one(7, 4, test_input) print("part one:", part_one(31, 39, puzzle_input))
part one: 96
def part_two(favourite_number): grid = build_grid(50, 50, favourite_number) distances = [ [ math.inf for c in range(51)] for r in range(51) ] queue = [] heappush(queue, (0, (1, 1))) while len(queue) > 0: steps, (r, c) = heappop(queue) if grid[r][c] == "#" or steps > 50 or steps > distances[r][c]: continue distances[r][c] = steps for (nr, nc) in neighbours4(grid, r, c): heappush(queue, (steps+1, (nr, nc))) reachable_in_50 = 0 for row in distances: for col in row: if col <= 50: reachable_in_50 += 1 return reachable_in_50 print("part two:", part_two(puzzle_input))
part two: 141