Solve 2021 day 22

This commit is contained in:
felixm 2024-11-30 12:22:44 -05:00
parent 2d3a44760e
commit 54bbc228f4
2 changed files with 71 additions and 6 deletions

View File

@ -1,5 +1,7 @@
from lib import get_data from lib import get_data
from lib import ints from lib import ints
from dataclasses import dataclass
from typing import Optional
data = get_data(__file__) data = get_data(__file__)
@ -17,11 +19,74 @@ for i, line in enumerate(data.splitlines()):
ps.remove((x, y, z)) ps.remove((x, y, z))
else: else:
assert False assert False
print(len(ps)) print(len(ps))
# For part 1, we were limited to an area of -50..50 for all three directions. @dataclass
# For part 2, this limitation is no longer in place. That means we cannot keep class Line:
# track of all the points individually. Instead, it will be necessary. To keep a: int
# track of regions. Ultimately, we then have to perform arithmetic on the b: int
# regions. This is not trivial enough for me right now.
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))

View File

@ -193,7 +193,7 @@ Solutions and utility script for Advent of Code challenges in Python.
- Day 19: - Day 19:
- Day 20: 105:00 (That wasn't easy but was able to solve in one go.) - 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 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 23: 81:38 (Fun but obviously not competitive.)
- Day 24: 232:00 (Super hard for me but I am proud of it.) - 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.) - Day 25: 15:43 (That could have been much much faster.)