def iter(
     self,
     limit_min: Optional[Point3D] = None,
     limit_max: Optional[Point3D] = None,
 ) -> Iterable[Point3D]:
     if limit_min is None:
         limit_min = self.min
     if limit_max is None:
         limit_max = self.max
     xs = range(
         max(limit_min.x, self.min.x),
         min(limit_max.x, self.max.x) + 1,
     )
     ys = range(
         max(limit_min.y, self.min.y),
         min(limit_max.y, self.max.y) + 1,
     )
     zs = range(
         max(limit_min.z, self.min.z),
         min(limit_max.z, self.max.z) + 1,
     )
     for x in xs:
         for y in ys:
             for z in zs:
                 yield Point3D(x, y, z)
Ejemplo n.º 2
0
    def play(self) -> None:
        lines = list(
            filter(
                None,
                map(
                    str.strip, """
        on x=-46..7,y=-6..46,z=-50..-1
        on x=-49..1,y=-3..46,z=-24..28
        on x=2..47,y=-22..22,z=-23..27
        on x=-27..23,y=-28..26,z=-21..29
        on x=-39..5,y=-6..47,z=-3..44
        on x=-30..21,y=-8..43,z=-13..34
        on x=-22..26,y=-27..20,z=-29..19
        off x=-48..-32,y=26..41,z=-47..-37
        """.splitlines())))

        texts = map(
            "\n".join,
            chain(*[
                combinations(lines, length)
                for length in range(len(lines) + 1)
            ]))
        original_constraint = Region3D(Point3D(-50, -50, -50),
                                       Point3D(50, 50, 50))
        mismatching_texts_and_values = (
            (text, old_value, new_value) for text in texts
            for old_value in [Reactor.from_steps_text(text).cube_count]
            for new_value in [
                len(
                    Region3DSet.from_steps_text(text).intersect(
                        original_constraint)),
            ] if old_value != new_value)
        first_mismatching_text_and_values = \
            next(mismatching_texts_and_values, None)
        if not first_mismatching_text_and_values:
            print("All match!")
            return

        (
            first_mismatching_text,
            first_mismatching_old_value,
            first_mismatching_new_value,
        ) = first_mismatching_text_and_values

        print(f"New {first_mismatching_new_value} "
              f"!= old {first_mismatching_old_value}")
        print(first_mismatching_text)
 def from_step_text(cls, step_text: str) -> "RebootStep":
     """
     >>> RebootStep.from_step_text("on x=-45..7,y=-17..27,z=5..49")
     RebootStep(min=Point3D(x=-45, y=-17, z=5), max=Point3D(x=7, y=27, z=49),
         set_to_on=True)
     >>> RebootStep.from_step_text("off x=-30..-17,y=-18..-5,z=-54..-31")
     RebootStep(min=Point3D(x=-30, y=-18, z=-54),
         max=Point3D(x=-17, y=-5, z=-31),
         set_to_on=False)
     """
     set_to_on_str, *min_and_max_str = \
         cls.re_step.match(step_text.strip()).groups()
     min_x, max_x, min_y, max_y, min_z, max_z = map(int, min_and_max_str)
     return cls(
         min=Point3D(min_x, min_y, min_z),
         max=Point3D(max_x, max_y, max_z),
         set_to_on=cls.SET_TO_ON_MAP[set_to_on_str],
     )
Ejemplo n.º 4
0
    def from_robot_text(cls, robot_text):
        """
        >>> Robot.from_robot_text("pos=<0,0,0>, r=4")
        Robot(position=Point3D(x=0, y=0, z=0), radius=4)
        """
        x_str, y_str, z_str, radius_str = \
            cls.re_robot.match(robot_text).groups()
        position = Point3D.from_int_texts(x_str, y_str, z_str)
        radius = int(radius_str)

        return cls(position, radius)
    def __setitem__(self, key: Point3D, value: bool) -> None:
        value = bool(value)
        old_value = self[key]
        if old_value == value:
            return

        if value:
            if not key.is_bound(self.min, self.max):
                return
            self.cubes.add(key)
        else:
            self.cubes.remove(key)
class Reactor(Generic[RebootStepSetT]):
    cubes: Set[Point3D] = field(default_factory=set)
    min: Point3D = Point3D(-50, -50, -50)
    max: Point3D = Point3D(50, 50, 50)

    @classmethod
    def get_steps_class(cls) -> Type[RebootStepSetT]:
        return get_type_argument_class(cls, RebootStepSetT)

    @classmethod
    def from_steps_text(
            cls,
            steps_text: str,
            debugger: Debugger = Debugger(enabled=False),
    ) -> "Reactor":
        """
        >>> Reactor.from_steps_text('''
        ...     on x=10..12,y=10..12,z=10..12
        ...     on x=11..13,y=11..13,z=11..13
        ...     off x=9..11,y=9..11,z=9..11
        ...     on x=10..10,y=10..10,z=10..10
        ... ''').cube_count
        39
        >>> Reactor.from_steps_text('''
        ...     on x=-20..26,y=-36..17,z=-47..7
        ...     on x=-20..33,y=-21..23,z=-26..28
        ...     on x=-22..28,y=-29..23,z=-38..16
        ...     on x=-46..7,y=-6..46,z=-50..-1
        ...     on x=-49..1,y=-3..46,z=-24..28
        ...     on x=2..47,y=-22..22,z=-23..27
        ...     on x=-27..23,y=-28..26,z=-21..29
        ...     on x=-39..5,y=-6..47,z=-3..44
        ...     on x=-30..21,y=-8..43,z=-13..34
        ...     on x=-22..26,y=-27..20,z=-29..19
        ...     off x=-48..-32,y=26..41,z=-47..-37
        ...     on x=-12..35,y=6..50,z=-50..-2
        ...     off x=-48..-32,y=-32..-16,z=-15..-5
        ...     on x=-18..26,y=-33..15,z=-7..46
        ...     off x=-40..-22,y=-38..-28,z=23..41
        ...     on x=-16..35,y=-41..10,z=-47..6
        ...     off x=-32..-23,y=11..30,z=-14..3
        ...     on x=-49..-5,y=-3..45,z=-29..18
        ...     off x=18..30,y=-20..-8,z=-3..13
        ...     on x=-41..9,y=-7..43,z=-33..15
        ...     on x=-54112..-39298,y=-85059..-49293,z=-27449..7877
        ...     on x=967..23432,y=45373..81175,z=27513..53682
        ... ''').cube_count
        590784
        """
        steps_class = cls.get_steps_class()
        steps = steps_class.from_steps_text(steps_text)
        return cls().apply(steps, debugger=debugger)

    def __getitem__(self, item: Point3D) -> bool:
        return item in self.cubes

    def __setitem__(self, key: Point3D, value: bool) -> None:
        value = bool(value)
        old_value = self[key]
        if old_value == value:
            return

        if value:
            if not key.is_bound(self.min, self.max):
                return
            self.cubes.add(key)
        else:
            self.cubes.remove(key)

    @property
    def cube_count(self) -> int:
        return len(self.cubes)

    def apply(
            self,
            steps: RebootStepSetT,
            debugger: Debugger = Debugger(enabled=False),
    ) -> "Reactor":
        steps.apply(self, debugger=debugger)

        return self
Ejemplo n.º 7
0
 def setPos(self,x,y,z):
   self.pos = Point3D(x,y,z)
Ejemplo n.º 8
0
 def __init__(self):
   self.radius = 0.11 #m
   self.weight = 0.43 #kg
   self.pos = Point3D(0,0,0)