-
Notifications
You must be signed in to change notification settings - Fork 0
/
aoc_22b.py
63 lines (48 loc) · 1.66 KB
/
aoc_22b.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
with open("input_22.txt") as fin:
seq = []
for line in fin:
state, rest = line.strip().split(" ")
state = 1 if state == "on" else 0
for c in ",.xyz=":
rest = rest.replace(c, " ")
xmin, xmax, ymin, ymax, zmin, zmax = [int(s) for s in rest.split()]
seq.append((state, ((xmin, xmax), (ymin, ymax), (zmin, zmax))))
def intersect_edge(edge1, edge2):
lo = max(edge1[0], edge2[0])
hi = min(edge1[1], edge2[1])
if lo > hi:
return None
else:
return lo, hi
def intersect_cube(cube1, cube2):
# return overlap cube from two given cubes
# a cube is a triple of pairs
# ((xmin,xmax),(ymin,ymax),(zmin,zmax))
temp = []
for i in range(3):
int_edge = intersect_edge(cube1[i], cube2[i])
if int_edge is None:
return None
temp.append(int_edge)
return tuple(temp)
from collections import defaultdict
# collecting all input cubes and overlap cubes with their "weight"
field = defaultdict(int)
for state, curr_inputcube in seq:
all_contrib = defaultdict(int) # collects the weights that need to be annulled
for cube in field:
int_cube = intersect_cube(curr_inputcube, cube)
if int_cube:
all_contrib[int_cube] += field[cube]
for cube in all_contrib: # apply cumulative changes to field
field[cube] -= all_contrib[cube]
if state == 1: # finally, insert the current input cube if "on"
field[curr_inputcube] += 1
def vol(cube):
v = 1
for i in range(3):
edge = cube[i]
v *= edge[1] - edge[0] + 1
return v
total = sum(field[cube] * vol(cube) for cube in field)
print(total)