summaryrefslogtreecommitdiff
path: root/22_2021.py
blob: 8336a38ba561ab76e1d3694cb3836ee5455cb88c (plain)
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
data = open("day22data.txt").read().splitlines()
dims = {"x": 0, "y": 1, "z": 2}


class Cubes:
    def __init__(self, limits, state):
        self.state = state
        self.limits = limits
        self.corners = set()
        for x in limits["x"]:
            for y in limits["y"]:
                for z in limits["z"]:
                    self.corners.add((x, y, z))
        self.removed = []

    def inside(self, point):
        for dim in self.limits:
            if (
                self.limits[dim][0] > point[dims[dim]]
                or self.limits[dim][1] < point[dims[dim]]
            ):
                return False
        return True

    def combineWith(self, other):
        overlapLimits = self.overlap(other)
        if overlapLimits:
            self.removeCube(Cubes(overlapLimits, "off"))
            return True
        else:
            return False

    def removeCube(self, other):
        for rem in self.removed:
            rem.combineWith(other)
        self.removed.append(other)

    def overlap(self, other):
        overlapLimits = {}
        for dim in self.limits:
            thisMin = self.limits[dim][0]
            thisMax = self.limits[dim][1]
            otherMin = other.limits[dim][0]
            otherMax = other.limits[dim][1]
            overlapMin = max(thisMin, otherMin)
            overlapMax = min(thisMax, otherMax)
            if overlapMin <= overlapMax:
                overlapLimits[dim] = [overlapMin, overlapMax]
            else:
                return None
        return overlapLimits

    def volume(self):
        vol = 1
        for dim in self.limits:
            vol *= self.limits[dim][1] - self.limits[dim][0] + 1
        removedVol = 0
        for rem in self.removed:
            removedVol += rem.volume()
        return vol - removedVol


cubes = {}
cubesA = {}
cubeA = Cubes({"x": [-50, 50], "y": [-50, 50], "z": [-50, 50]}, "A")
id = 0
idA = 0
for rule in data:
    state, poses = rule.split()
    poses = [x.split("=") for x in poses.split(",")]
    vals = {}
    for pos in poses:
        vals[pos[0]] = [int(x) for x in pos[1].split("..")]
    newCube = Cubes(vals, state)
    overlapA = cubeA.overlap(newCube)
    if overlapA:
        newCubeA = Cubes(overlapA, state)
        for j in range(idA):
            cubesA[j].combineWith(newCubeA)
        if state == "on":
            cubesA[idA] = newCubeA
            idA += 1
    for i in range(id):
        cubes[i].combineWith(newCube)
    if state == "on":
        cubes[id] = newCube
        id += 1
totVolA = 0
for c in cubesA:
    totVolA += cubesA[c].volume()
totVol = 0
for c in cubes:
    totVol += cubes[c].volume()
print(totVolA)
print(totVol)