···11+# Python adaptation of Peter Tseng's day 22 solution
22+# https://www.reddit.com/r/adventofcode/comments/5jor9q/2016_day_22_solutions/dbhw73s
33+44+import re
55+import fileinput
66+from itertools import permutations
77+from collections import deque, namedtuple
88+99+WIDTH = None
1010+HEIGHT = None
1111+DIRS = {(1, 0), (-1, 0), (0, 1), (0, -1)}
1212+1313+Node = namedtuple('Point', 'x y size used available used_pcnt')
1414+1515+1616+def naive_move_to_top(node, grid):
1717+ queue = deque([(node.x, node.y)])
1818+ dists = {(node.x, node.y): 0}
1919+2020+ while queue:
2121+ x, y = queue.pop()
2222+2323+ if y == 0:
2424+ return dists[x, y], x
2525+2626+ for dx, dy in DIRS:
2727+ nx, ny = x + dx, y + dy
2828+2929+ if not (0 <= nx < WIDTH and 0 <= ny < HEIGHT):
3030+ continue
3131+3232+ if (nx, ny) in dists or grid[ny][nx].used > grid[y][x].size:
3333+ continue
3434+3535+ dists[nx, ny] = dists[x, y] + 1
3636+ queue.appendleft((nx, ny))
3737+3838+3939+def sliding_tile_moves(node, grid):
4040+ # Move the empty spot to y=0 and track x position.
4141+ steps, x = naive_move_to_top(node, grid)
4242+4343+ # Move to (WIDTH - 2, 0), one to the left of the goal.
4444+ steps += WIDTH - 2 - x
4545+4646+ # 1 step moves the goal data into (WIDTH - 2, 0), with empty space behind.
4747+ steps += 1
4848+4949+ # 4 steps each to move the empty space from behind to in front,
5050+ # 1 step to move the goal data
5151+ return steps + 5 * (WIDTH - 2)
5252+5353+5454+if __name__ == '__main__':
5555+ nodes = []
5656+5757+ for line in fileinput.input():
5858+ if line.startswith('/dev/grid/'):
5959+ data = (int(x) for x in re.findall(r'(\d+)', line))
6060+ nodes.append(Node(*data))
6161+6262+ WIDTH = 1 + max(node.x for node in nodes)
6363+ HEIGHT = 1 + max(node.y for node in nodes)
6464+6565+ grid = [[None for _ in range(WIDTH)] for _ in range(HEIGHT)]
6666+6767+ for node in nodes:
6868+ grid[node.y][node.x] = node
6969+7070+ pairs = set()
7171+7272+ for a, b in permutations(nodes, 2):
7373+ if a.used > 0 and a.used <= b.available:
7474+ pairs.add((a, b))
7575+7676+ print "Viable pairs of nodes:", len(pairs)
7777+7878+ empties = [n for n in nodes if n.used == 0]
7979+ fewest_steps = min(sliding_tile_moves(e, grid) for e in empties)
8080+ print "Fewest steps to move goal data:", fewest_steps