-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday19.krk
130 lines (108 loc) · 3.44 KB
/
day19.krk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env kuroko
'''
day 19
'''
import fileio
import kuroko
let data
with fileio.open(kuroko.argv[1] if len(kuroko.argv) > 1 else kuroko.argv[0].replace('.krk','.txt'),'r') as f:
data = f.readlines()
let lines = [line.strip() for line in data]
# Input processing
let current = None
let scanners = {}
for line in lines:
if not line:
continue
if line.startswith('---'):
current = int(line.split(' ')[2])
scanners[current] = []
continue
if current is None:
continue
scanners[current].append(tuple(int(x) for x in line.split(',')))
# Coordinate spaces
let x, y, z = 0,1,2
let pos = 1
let neg = -1
let orientations = [
((pos, x), (pos, y), (pos, z)),
((pos, x), (neg, z), (pos, y)),
((pos, x), (neg, y), (neg, z)),
((pos, x), (pos, z), (neg, y)),
((pos, z), (pos, x), (pos, y)),
((pos, z), (neg, y), (pos, x)),
((pos, z), (neg, x), (neg, y)),
((pos, z), (pos, y), (neg, x)),
((pos, y), (pos, z), (pos, x)),
((pos, y), (neg, x), (pos, z)),
((pos, y), (neg, z), (neg, x)),
((pos, y), (pos, x), (neg, z)),
((neg, x), (pos, z), (pos, y)),
((neg, x), (neg, y), (pos, z)),
((neg, x), (neg, z), (neg, y)),
((neg, x), (pos, y), (neg, z)),
((neg, z), (pos, y), (pos, x)),
((neg, z), (neg, x), (pos, y)),
((neg, z), (neg, y), (neg, x)),
((neg, z), (pos, x), (neg, y)),
((neg, y), (pos, x), (pos, z)),
((neg, y), (neg, z), (pos, x)),
((neg, y), (neg, x), (neg, z)),
((neg, y), (pos, z), (neg, x)),
]
def transcribe_transformation(orient):
let labels = ['x','y','z']
let dirs = ['-','','+']
return ','.join(dirs[x+1] + labels[y] for x,y in orient)
# Matching
from collections import defaultdict
def dist(pt1,pt2,orient):
return (
pt2[0] - pt1[orient[0][1]] * orient[0][0],
pt2[1] - pt1[orient[1][1]] * orient[1][0],
pt2[2] - pt1[orient[2][1]] * orient[2][0]
)
let beacons = {}
# There is always a 0 scanner, so use it as the basis
for pt in scanners[0]:
beacons[pt] = 1
def add_beacon(mp,pt,orient,offset):
mp[(
pt[orient[0][1]] * orient[0][0] + offset[0],
pt[orient[1][1]] * orient[1][0] + offset[1],
pt[orient[2][1]] * orient[2][0] + offset[2]
)] = 1
let scanner_positions = {0: (0,0,0)}
let next = [x for x in scanners.keys()]
for i in next:
let found = False
for orient in orientations:
let binnings = defaultdict(lambda: 0)
for pt1 in scanners[i]:
for pt2 in beacons.keys():
binnings[dist(pt1,pt2,orient)] += 1
for x,y in binnings.items():
if y >= 12:
found = True
print(i,"has",y,"overlaps when oriented",transcribe_transformation(orient),"at position",x)
scanner_positions[i] = x
for pt in scanners[i]:
add_beacon(beacons,pt,orient,x)
break
if found: # Labeled breaks sure would be nice...
break
if not found:
next.append(i)
print(len(beacons),"beacons after reconciliation")
print("Positions of all scanners:",scanner_positions)
# Distances
def mdist(pt1,pt2):
return abs(pt1[0]-pt2[0])+abs(pt1[1]-pt2[1])+abs(pt1[2]-pt2[2])
let top = 0
for i in scanners.keys():
for j in scanners.keys():
let d = mdist(scanner_positions[i],scanner_positions[j])
if d > top:
top = d
print(top,"maximum manhattan distance between scanners")