Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from typing import List
- from sys import argv
- import requests
- import os
- from itertools import product
- class Cuboid:
- def __init__(self, x, y, z) -> None:
- self.x = x
- self.y = y
- self.z = z
- def __str__(self) -> str:
- return "Cube(%s,%s,%s)" % (str(self.x), str(self.y), str(self.z))
- def volume(self):
- x1, x2 = self.x
- y1, y2 = self.y
- z1, z2 = self.z
- return (x1 - x2 + 1) * (y1 - y2 + 1) * (z1 - z2 + 1)
- def intersect(self, i1, i2):
- x, y = i1
- s, t = i2
- if not (s > y or t < x):
- return (max(x, s), min(y, t))
- else:
- return (x,y)
- def minus(self, i1, i2):
- s, t = self.intersect(i1, i2)
- x, y = i1
- if x <= s <= t <= y:
- intervals = []
- if t != y:
- intervals.append((t + 1, y))
- if s != x:
- intervals.append((x, s - 1))
- return intervals
- elif x <= s <= y and t > y:
- if s != x:
- return [(x, s - 1)]
- return []
- elif s < x and x <= t <= y:
- if t != y:
- return [(t + 1, y)]
- return []
- else:
- return [(x, y)]
- def overlap(self, other: 'Cuboid'):
- x = self.intersect(self.x, other.x)
- y = self.intersect(self.y, other.y)
- z = self.intersect(self.z, other.z)
- return Cuboid(x, y, z)
- def subtract(self, other: 'Cuboid'):
- xs = self.minus(self.x, other.x)
- ys = self.minus(self.y, other.y)
- zs = self.minus(self.z, other.z)
- if max(xs, ys, zs, key=len) == 0:
- return []
- else:
- if len(xs) == 0:
- xs.append(self.x)
- if len(ys) == 0:
- ys.append(self.y)
- if len(zs) == 0:
- zs.append(self.z)
- cuboids = []
- for r in product(xs, ys, zs):
- x,y,z = r
- cuboids.append(Cuboid(x, y, z))
- return cuboids
- def merge(self, other: 'Cuboid'):
- overlap = self.overlap(other)
- if self.x == overlap.x and self.y == overlap.y and self.z == overlap.z:
- return []
- return self.subtract(other) + other.subtract(self) + [overlap]
- def part2(lines: List[str]):
- on_ranges = set()
- off_ranges = set()
- for l in lines:
- state, ranges = l.split(" ")
- axis_ranges = ranges.split(",")
- x_range = axis_ranges[0].split("=")[1].split("..")
- y_range = axis_ranges[1].split("=")[1].split("..")
- z_range = axis_ranges[2].split("=")[1].split("..")
- x1, x2 = int(x_range[0]), int(x_range[1])
- y1, y2 = int(y_range[0]), int(y_range[1])
- z1, z2 = int(z_range[0]), int(z_range[1])
- if state == "on":
- on_ranges.add(((x1, x2), (y1, y2), (z1, z2)))
- else:
- off_ranges.add(((x1, x2), (y1, y2), (z1, z2)))
- print(on_ranges)
- turned_on: list[Cuboid] = []
- for r in on_ranges:
- x, y, z = r
- cube = Cuboid(x, y, z)
- new = []
- for t in turned_on:
- new.extend(cube.merge(t))
- if len(new) == 0:
- turned_on.append(cube)
- else:
- turned_on = new
- for r in off_ranges:
- x, y, z = r
- cube = Cuboid(x, y, z)
- new = []
- for t in turned_on:
- new.extend(t.subtract(cube))
- turned_on = new
- total_on = 0
- for t in turned_on:
- total_on += t.volume()
- return total_on
Advertisement
Add Comment
Please, Sign In to add comment