예제 #1
0
 def axis(self) -> Vector:
     if self.__root__ == "N":
         return Vector(x=0, y=1)
     elif self.__root__ == "W":
         return Vector(x=-1, y=0)
     elif self.__root__ == "S":
         return Vector(x=0, y=-1)
     elif self.__root__ == "E":
         return Vector(x=1, y=0)
     else:
         assert_never(self.__root__)
예제 #2
0
    def run_step(self) -> None:
        self._visited_indices.add(self._current_index)
        current_instruction = self.instructions[self._current_index]

        if isinstance(current_instruction, Acc):
            self._accumulator += current_instruction.value
            self._current_index += 1
        elif isinstance(current_instruction, Nop):
            self._current_index += 1
        elif isinstance(current_instruction, Jmp):
            self._current_index += current_instruction.offset
        else:
            assert_never(current_instruction.code)
예제 #3
0
    def part1(self) -> int:
        mask = None
        result: Dict[int, int] = {}
        for instruction in self.puzzle.data:
            if isinstance(instruction, Mask):
                mask = instruction
            elif isinstance(instruction, MemSet):
                bitstring = instruction.value_as_bitstring()
                if mask:
                    bitstring = mask.apply_to(bitstring)
                result[instruction.address] = int(bitstring, 2)
            else:
                assert_never(instruction)

        return sum(result.values())
예제 #4
0
    def part2(self) -> int:
        for index, instruction in enumerate(self.puzzle.data):
            if instruction.code == "acc":
                continue
            elif instruction.code == "jmp":
                new_instruction_set = self._mutate_instruction(index, Nop)
            elif instruction.code == "nop":
                new_instruction_set = self._mutate_instruction(index, Jmp)
            else:
                assert_never(instruction.code)

            interpreter = Interpreter(new_instruction_set)

            try:
                return interpreter.run()
            except LoopDetected:
                pass
        raise NoResultFoundException
예제 #5
0
    def part2(self) -> int:
        mask = None
        result: Dict[int, int] = {}
        for instruction in self.puzzle.data:
            if isinstance(instruction, Mask):
                mask = instruction
            elif isinstance(instruction, MemSet):
                if not mask:
                    result[instruction.address] = instruction.value
                else:
                    masked_addr = mask.apply_to_addr(
                        instruction.address_as_bitstring())
                    for sub_mask in masked_addr.generate_all_values():
                        addr = int(sub_mask.str_repr, 2)
                        result[addr] = instruction.value
            else:
                assert_never(instruction)

        return sum(result.values())
예제 #6
0
 def part1(self) -> int:
     boat = Boat.starting_position()
     for instruction in self.puzzle.data:
         if isinstance(instruction.action, Direction):
             shift = instruction.action.axis * instruction.value
             boat.coord += shift
         elif instruction.action == "F":
             shift = boat.direction.axis * instruction.value
             boat.coord += shift
         # `action in ["L", "R"]` makes mypy fail to see we can never reach the `assert_never` (mypy 0.790)
         elif instruction.action == "L" or instruction.action == "R":
             rotation_number = instruction.value // 90
             if instruction.action == "L":
                 rotation_number *= -1
             boat.direction = Direction.clockwise(
                 from_=boat.direction)[rotation_number]
         else:
             assert_never(instruction)
     return boat.coord.manhattan_distance
예제 #7
0
 def part2(self) -> int:
     boat = Boat.starting_position()
     for instruction in self.puzzle.data:
         if isinstance(instruction.action, Direction):
             shift = instruction.action.axis * instruction.value
             boat.waypoint_offset += shift
         elif instruction.action == "F":
             shift = boat.waypoint_offset * instruction.value
             boat.coord += shift
         elif instruction.action == "L" or instruction.action == "R":
             rotation_number = instruction.value // 90
             if instruction.action == "L":
                 rotation_number *= 3
             for _ in range(rotation_number):
                 boat.waypoint_offset = boat.waypoint_offset.rotate_clockwise(
                 )
         else:
             assert_never(instruction)
     return boat.coord.manhattan_distance