diff --git a/day22/lib/classes.py b/day22/lib/classes.py index 38caa14..0fa48e8 100644 --- a/day22/lib/classes.py +++ b/day22/lib/classes.py @@ -20,10 +20,14 @@ class BoxData: init=False, repr=False, hash=False, default=None ) supports: set["BoxData"] = field( - default_factory=set, hash=False, repr=False + default_factory=set, hash=False, repr=False, init=False ) # list of blocks we support - hats: set["BoxData"] = field(default_factory=set, hash=False, repr=False) - total_hats: set["BoxData"] = field(default_factory=set, hash=False, repr=False) + hats: set["BoxData"] = field( + default_factory=set, hash=False, repr=False, init=False + ) + total_hats: set["BoxData"] = field( + default_factory=set, hash=False, repr=False, init=False + ) @property def vpos(self) -> vpython.vector: @@ -44,9 +48,6 @@ def width(self) -> float: def height(self) -> float: return float(self.end_pos.z - self.start_pos.z + 1) - def set_vbox(self, vbox: vpython.box) -> None: - self.vbox = vbox - @property def z_val_bot(self) -> int: """return lowest z value (self.start_pos.z)""" @@ -57,23 +58,33 @@ def z_val_top(self) -> int: """return maximum z value(self.end_pos.z)""" return self.end_pos.z + #################################### + # Visualisation calls (not ci'ed) # + #################################### + def set_vbox(self, vbox: vpython.box) -> None: # pragma: no cover + self.vbox = vbox + def fall(self) -> None: self.start_pos.z -= 1 self.end_pos.z -= 1 # vbox y == boxdata z - if self.vbox is not None: + if self.vbox is not None: # pragma: no cover self.vbox.pos.y -= 1 def select(self) -> None: - if self.vbox is not None: + if self.vbox is not None: # pragma: no cover self.vbox.pos.x += 30 self.vbox.pos.z -= 30 def unselect(self) -> None: - if self.vbox is not None: + if self.vbox is not None: # pragma: no cover self.vbox.pos.x -= 30 self.vbox.pos.z += 30 + ################################################ + # Calculations; supports, hats, recursive fall # + ################################################ + def set_supports(self, supports: set["BoxData"]) -> None: """blocks under us""" self.supports = supports @@ -81,9 +92,6 @@ def set_supports(self, supports: set["BoxData"]) -> None: def set_hats(self, hats: set["BoxData"]) -> None: self.hats = hats - def __hash__(self) -> int: - return hash(f"{self.start_pos} | {self.end_pos}") - def recursive_fall(self, already_falling: set["BoxData"]) -> set["BoxData"]: """returns all boxes above us that fall if we fall""" to_process: list[BoxData] = [] # items that will fall if this brick is removed @@ -103,6 +111,9 @@ def recursive_fall(self, already_falling: set["BoxData"]) -> set["BoxData"]: return result + def __hash__(self) -> int: + return hash(f"{self.start_pos} | {self.end_pos}") + class Matrix: # z, x, y @@ -131,10 +142,7 @@ def register_box(self, box: BoxData) -> None: for x in range(box.start_pos.x, box.end_pos.x + 1): for y in range(box.start_pos.y, box.end_pos.y + 1): if self.layers[z][x][y] is not None: - print("collision at:", (x, y, z)) - print(f"collision with: {self.layers[z][x][y]}") - print(f"trying to insert: {box}") - raise ValueError(":o verlap") + raise AssertionError("Overlap should not occur") self.layers[z][x][y] = box diff --git a/day22/tests/test_classes.py b/day22/tests/test_classes.py new file mode 100644 index 0000000..02509c3 --- /dev/null +++ b/day22/tests/test_classes.py @@ -0,0 +1,17 @@ +from typing import TYPE_CHECKING + +from day22.lib.classes import BoxData, Vector3 + +if TYPE_CHECKING: + import vpython + + +def test_box_data() -> None: + start: Vector3 = Vector3(1, 1, 1) + end: Vector3 = Vector3(1, 4, 1) + box: BoxData = BoxData("memes", start, end) + vec: vpython.vector = box.vpos + # our source z is vpython's y + assert vec.x == 1.5 + assert vec.z == 3.0 + assert vec.y == 1.5