Solve 2021 day 22
This commit is contained in:
parent
2d3a44760e
commit
54bbc228f4
75
2021/d22.py
75
2021/d22.py
@ -1,5 +1,7 @@
|
||||
from lib import get_data
|
||||
from lib import ints
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
data = get_data(__file__)
|
||||
|
||||
@ -17,11 +19,74 @@ for i, line in enumerate(data.splitlines()):
|
||||
ps.remove((x, y, z))
|
||||
else:
|
||||
assert False
|
||||
|
||||
print(len(ps))
|
||||
|
||||
|
||||
# For part 1, we were limited to an area of -50..50 for all three directions.
|
||||
# For part 2, this limitation is no longer in place. That means we cannot keep
|
||||
# track of all the points individually. Instead, it will be necessary. To keep
|
||||
# track of regions. Ultimately, we then have to perform arithmetic on the
|
||||
# regions. This is not trivial enough for me right now.
|
||||
@dataclass
|
||||
class Line:
|
||||
a: int
|
||||
b: int
|
||||
|
||||
def intersects(self, other: "Line") -> bool:
|
||||
return self.b > other.a and self.a < other.b
|
||||
|
||||
def intersection(self, other: "Line") -> Optional["Line"]:
|
||||
if not self.intersects(other):
|
||||
return None
|
||||
return Line(max(self.a, other.a), min(self.b, other.b))
|
||||
|
||||
def length(self) -> int:
|
||||
assert self.b > self.a
|
||||
return self.b - self.a + 1
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Cube:
|
||||
on: bool
|
||||
x: Line
|
||||
y: Line
|
||||
z: Line
|
||||
|
||||
@classmethod
|
||||
def from_line(cls, line: str) -> "Cube":
|
||||
xs = ints(line)
|
||||
assert len(xs) == 6
|
||||
lines = [Line(*xs[i:i+2]) for i in range(0, len(xs), 2)]
|
||||
on = True if line.startswith("on") else False
|
||||
return Cube(on, *lines)
|
||||
|
||||
def volume(self) -> int:
|
||||
return (self.x.length() * self.y.length() * self.z.length()) * (1 if self.on else -1)
|
||||
|
||||
def intersects(self, other: "Cube") -> bool:
|
||||
return (
|
||||
self.x.intersects(other.x)
|
||||
and self.y.intersects(other.y)
|
||||
and self.z.intersects(other.z)
|
||||
)
|
||||
|
||||
def intersection(self, other: "Cube") -> Optional["Cube"]:
|
||||
x = self.x.intersection(other.x)
|
||||
y = self.y.intersection(other.y)
|
||||
z = self.z.intersection(other.z)
|
||||
if x is None or y is None or z is None:
|
||||
return None
|
||||
return Cube(not self.on, x, y, z)
|
||||
|
||||
|
||||
# Inclusion/exclusion principle from set theory
|
||||
cubes = []
|
||||
for line in data.splitlines():
|
||||
cc = Cube.from_line(line)
|
||||
ncubes = []
|
||||
for i in range(len(cubes)):
|
||||
c = cubes[i]
|
||||
ic = c.intersection(cc)
|
||||
if ic is not None:
|
||||
cubes.append(ic)
|
||||
|
||||
if cc.on:
|
||||
cubes.append(cc)
|
||||
|
||||
print(sum(c.volume() for c in cubes))
|
||||
|
@ -193,7 +193,7 @@ Solutions and utility script for Advent of Code challenges in Python.
|
||||
- Day 19:
|
||||
- Day 20: 105:00 (That wasn't easy but was able to solve in one go.)
|
||||
- Day 21: 37:45 (Wasn't hard but I was just too slow.)
|
||||
- Day 22:
|
||||
- Day 22: 142:00 (Wonderful problem and hard for me but learned something new for sure.)
|
||||
- Day 23: 81:38 (Fun but obviously not competitive.)
|
||||
- Day 24: 232:00 (Super hard for me but I am proud of it.)
|
||||
- Day 25: 15:43 (That could have been much much faster.)
|
||||
|
Loading…
Reference in New Issue
Block a user