|
@@ -0,0 +1,64 @@
|
|
1
|
+#!/usr/bin/python3
|
|
2
|
+
|
|
3
|
+"""Solution for day 22 of Advent of Code 2016.
|
|
4
|
+
|
|
5
|
+Part 1 is straight-forward reading of the data, generating pairs using itertools.permutations, and counting how
|
|
6
|
+many match the criteria.
|
|
7
|
+
|
|
8
|
+As is traditional at about this point in Advent of Code, part 2 requires you to make annoying assumptions based on
|
|
9
|
+the vague example in the question and some properties of your input that you have no guarantee are universal.
|
|
10
|
+
|
|
11
|
+In this case, the input needs to be partitioned in to three sets: empty nodes (of which there is just one), giant
|
|
12
|
+nodes (whose data can't possibly be placed anywhere else) and normal nodes (who can shift their data to the empty
|
|
13
|
+node, but not to any other normal node).
|
|
14
|
+
|
|
15
|
+When the nodes are printed out according to their type (as in the example), it becomes obvious that there's a "wall"
|
|
16
|
+of giant nodes in the way. As the only valid moves involve the empty node, you basically have to move that around and
|
|
17
|
+use it to move the data along the top row.
|
|
18
|
+
|
|
19
|
+For my input, it takes 34 moves to rearrange things and then move the target data left by one:
|
|
20
|
+
|
|
21
|
+..............23456789012345678901234
|
|
22
|
+..............1......................
|
|
23
|
+..............0######################
|
|
24
|
+..............9876543................
|
|
25
|
+....................2................
|
|
26
|
+....................1................
|
|
27
|
+...................._................
|
|
28
|
+.....................................
|
|
29
|
+.....................................
|
|
30
|
+
|
|
31
|
+Then for each node to the left it takes an additional five moves, as the empty space loops around our target:
|
|
32
|
+
|
|
33
|
+....45_..
|
|
34
|
+....321..
|
|
35
|
+.........
|
|
36
|
+
|
|
37
|
+It needs to move a total of 35 nodes left, so 34+35*5 total moves = 209.
|
|
38
|
+"""
|
|
39
|
+
|
|
40
|
+import re
|
|
41
|
+
|
|
42
|
+import itertools
|
|
43
|
+
|
|
44
|
+matcher = re.compile(r'^/dev/grid/node-x([0-9]+)-y([0-9]+)\s+([0-9]+)T\s+([0-9]+)T\s+([0-9]+)T\s+.*$')
|
|
45
|
+
|
|
46
|
+# Constants used for convenient access the groups in the matcher above
|
|
47
|
+locx = 0
|
|
48
|
+locy = 1
|
|
49
|
+size = 2
|
|
50
|
+used = 3
|
|
51
|
+free = 4
|
|
52
|
+
|
|
53
|
+with open('data/22.txt', 'r') as data:
|
|
54
|
+ discs = [tuple(map(int, matcher.match(l).groups())) for l in data.readlines() if matcher.match(l)]
|
|
55
|
+ pairs = sum(1 for p in itertools.permutations(discs, 2) if 0 < p[0][used] <= p[1][free])
|
|
56
|
+ print('Part one: %s' % pairs)
|
|
57
|
+
|
|
58
|
+ print('Part two: ...')
|
|
59
|
+ grid = dict((disc[:locy+1], disc) for disc in discs)
|
|
60
|
+ for y in range(27):
|
|
61
|
+ print(''.join(['X' if (x,y) not in grid
|
|
62
|
+ else '_' if grid[(x, y)][used] == 0
|
|
63
|
+ else '#' if grid[(x, y)][used] > 150 # Arbitrary cut-off for "normal" vs "giant" nodes
|
|
64
|
+ else '.' for x in range(37)]))
|