-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path22.py
80 lines (56 loc) · 1.83 KB
/
22.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
from lib import *
input = read_input(2021, 22)
lines = input.splitlines()
def line_intersection(a1, a2, b1, b2):
if a2 < b1 or b2 < a1:
return None
return max(a1, b1), min(a2, b2)
@dataclass
class Cuboid:
x1: int
x2: int
y1: int
y2: int
z1: int
z2: int
off = None
def get_intersection(self, other):
x = line_intersection(self.x1, self.x2, other.x1, other.x2)
y = line_intersection(self.y1, self.y2, other.y1, other.y2)
z = line_intersection(self.z1, self.z2, other.z1, other.z2)
if None in [x, y, z]:
return None
return Cuboid(*x, *y, *z)
def subtract(self, other):
if intersection := self.get_intersection(other):
if not self.off:
self.off = []
for o in self.off:
o.subtract(other)
self.off.append(intersection)
def volume(self):
return (self.x2 - self.x1 + 1) * (self.y2 - self.y1 + 1) * (self.z2 - self.z1 + 1) - sum(
o.volume() for o in self.off or []
)
cuboids = []
for line in lines:
match = re.match(r"^(on|off) x=(-?\d+)..(-?\d+),y=(-?\d+)..(-?\d+),z=(-?\d+)..(-?\d+)$", line)
if any(x not in range(-50, 51) for x in map(int, match.groups()[1:])):
continue
on = match.group(1) == "on"
cuboid = Cuboid(*map(int, match.groups()[1:]))
for c in cuboids:
c.subtract(cuboid)
if on:
cuboids.append(cuboid)
print(sum(c.volume() for c in cuboids))
cuboids = []
for line in lines:
match = re.match(r"^(on|off) x=(-?\d+)..(-?\d+),y=(-?\d+)..(-?\d+),z=(-?\d+)..(-?\d+)$", line)
on = match.group(1) == "on"
cuboid = Cuboid(*map(int, match.groups()[1:]))
for c in cuboids:
c.subtract(cuboid)
if on:
cuboids.append(cuboid)
print(sum(c.volume() for c in cuboids))