-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathday18.py
95 lines (69 loc) · 1.66 KB
/
day18.py
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
import fileinput
from collections import deque
from utils import parse_nums, memoize
cubes = []
min_x = 1e9
max_x = -1e9
min_y = 1e9
max_y = -1e9
min_z = 1e9
max_z = -1e9
for line in fileinput.input():
x, y, z = parse_nums(line)
cubes.append((x, y, z))
min_x = min(x, min_x)
max_x = max(x, max_x)
min_y = min(y, min_y)
max_y = max(y, max_y)
min_z = min(z, min_z)
max_z = max(z, max_z)
cubes = set(cubes)
OFFSETS = [
(-1, 0, 0),
(1, 0, 0),
(0, -1, 0),
(0, 1, 0),
(0, 0, -1),
(0, 0, 1),
]
def outside(x, y, z):
xx = min_x <= x < max_x
yy = min_y <= y < max_y
zz = min_z <= z < max_z
return not (xx and yy and zz)
KNOWN_INTERNALS = set()
def is_internal(node):
global KNOWN_INTERNALS
seen = set()
horizon = deque([node])
while horizon:
n = horizon.popleft()
x, y, z = n
if n in seen:
continue
if n in KNOWN_INTERNALS:
return True
if outside(*n):
return False
seen.add(n)
for dx, dy, dz in OFFSETS:
nx = x + dx
ny = y + dy
nz = z + dz
if (nx, ny, nz) in cubes:
continue
horizon.append((nx, ny, nz))
# We are internal, so add everything we've seen to KNOWN_INTERNALS.
KNOWN_INTERNALS |= seen
return True
part_1 = 0
part_2 = 0
for x, y, z in cubes:
for dx, dy, dz in OFFSETS:
nx, ny, nz = x + dx, y + dy, z + dz
if (nx, ny, nz) not in cubes:
part_1 += 1
if not is_internal((nx, ny, nz)):
part_2 += 1
print("Part 1:", part_1)
print("Part 2:", part_2)