def find(self, debugger: Debugger = Debugger(enabled=False)) -> Paths:
        def reporting_format(_: Debugger, message: str) -> str:
            return (
                f"{message} ({len(paths)} found, {len(seen)} seen, "
                f"{len(stack)} in stack)"
            )

        paths = []
        stack: List[CaveFinderStateT] = [self.get_state_class().make_initial()]
        seen = {stack[0]}
        with debugger.adding_extra_report_format(reporting_format):
            debugger.default_report("Looking...")
            while debugger.step_if(stack):
                debugger.default_report_if("Looking...")
                state = stack.pop(0)
                for next_state in state.get_next_states(self.system.graph):
                    if next_state in seen:
                        continue
                    seen.add(next_state)
                    if next_state.is_terminal:
                        paths.append(next_state.path)
                        continue
                    stack.append(next_state)
            debugger.default_report("Finished looking")

        return paths
    def __mul__(
            self,
            count: int,
            debugger: Debugger = Debugger(enabled=False),
    ) -> "ModuloShuffle":
        cls = type(self)
        if count < 0:
            raise Exception(f"Cannot calculate negative count shuffle")

        # noinspection PyArgumentList
        total = cls(
            factor=1,
            offset=0,
            size=self.size,
        )
        power_shuffle = self
        power = 1
        remaining_count = count
        debugger.default_report(
            f"Remaining {math.ceil(math.log2(remaining_count))} rounds "
            f"({remaining_count}, {bin(remaining_count)})")
        while debugger.step_if(remaining_count):
            debugger.default_report_if(
                f"Remaining {math.ceil(math.log2(remaining_count))} rounds "
                f"({remaining_count}, {bin(remaining_count)})")
            if remaining_count % 2:
                total = total + power_shuffle
            remaining_count //= 2
            power *= 2
            power_shuffle = power_shuffle + power_shuffle

        return total
Exemple #3
0
    def step_many(self,
                  step_count: int,
                  debugger: Debugger = Debugger(enabled=False)):
        """
        >>> print("!" + Life.from_life_text(
        ...     ".#.#.#\\n"
        ...     "...##.\\n"
        ...     "#....#\\n"
        ...     "..#...\\n"
        ...     "#.#..#\\n"
        ...     "####..\\n"
        ... ).step_many(4).show())
        !......
        ......
        ..##..
        ..##..
        ......
        ......
        """
        current = self
        debugger.reset()
        for _ in debugger.stepping(range(step_count)):
            current = current.step()
            debugger.default_report_if()

        return current
Exemple #4
0
def get_nth_phase_message(
        initial: Union[str, Iterable[int]],
        length: Optional[int] = None,
        count: int = 100,
        message_offset: int = 0,
        debugger: Debugger = Debugger(enabled=False),
) -> str:
    """
    >>> get_nth_phase_message('12345678', count=4)
    '01029498'
    >>> get_nth_phase_message('80871224585914546619083218645595')
    '24176176'
    >>> get_nth_phase_message('19617804207202209144916044189917')
    '73745418'
    >>> get_nth_phase_message('69317163492948606335995924319873')
    '52432133'
    """
    if length is None:
        if not hasattr(initial, '__str__'):
            raise Exception(
                f"Initial has no length capability, and no length was passed")
        length = len(initial)
    if isinstance(initial, str):
        initial = list(map(int, initial))
    result = np.array(initial)
    # phase_patterns = list(map(list, get_phase_patterns(length)))
    debugger.default_report(f"Doing {count} iterations")
    for iteration in debugger.stepping(range(1, count + 1)):
        result = get_next_phase(result, length, debugger=debugger)
        debugger.default_report_if(f"Done {iteration}/{count}")
    return "".join(map(str, result[message_offset:message_offset + 8]))
Exemple #5
0
 def move_until_stop(
     self, debugger: Debugger = Debugger(enabled=False),
 ) -> Tuple[int, "Herd"]:
     """
     >>> _step_count, final = Herd.from_herd_text('''
     ...     v...>>.vv>
     ...     .vv>>.vv..
     ...     >>.>v>...v
     ...     >>v>>.>.v.
     ...     v>v.vv.v..
     ...     >.>>..v...
     ...     .vv..>.>v.
     ...     v.v..>>v.v
     ...     ....v..v.>
     ... ''').move_until_stop()
     >>> _step_count
     58
     >>> print(final)
     :.>>v>vv..
     ..v.>>vv..
     ..>>v>>vv.
     ..>>>>>vv.
     v......>vv
     v>v....>>v
     vvv.....>>
     >vv......>
     .>v.vv.v..
     """
     moved = self
     for step_count in debugger.stepping(count(1)):
         previous = moved
         moved = moved.move()
         debugger.default_report_if("Searching...")
         if moved == previous:
             return step_count, previous
    def get_index_at_position_after_shuffle_many(
            self,
            index,
            size,
            count,
            debugger: Debugger = Debugger(enabled=False),
    ):
        total_index = index
        shuffles = [
            shuffle.make_get_index_at_position_after_shuffle(size)
            for shuffle in reversed(self.shuffles)
        ]
        for step in debugger.stepping(range(count)):
            for shuffle in shuffles:
                total_index = shuffle(total_index)
            if total_index == index:
                break
            debugger.default_report_if(
                f"Looking {int(step / count * 10000) / 100}% "
                f"(current is {total_index})...")
        else:
            return total_index

        cycle_length = step + 1
        debugger.default_report(f"Found cycle of length {cycle_length}")

        for _ in debugger.stepping(range(count % cycle_length)):
            for shuffle in shuffles:
                total_index = shuffle(total_index)
            debugger.default_report_if(
                f"Finishing after cycle (current is {total_index})...")

        return total_index
 def get_index_cycle(
         self,
         index,
         size,
         max_count=None,
         debugger: Debugger = Debugger(enabled=False),
 ):
     """
     >>> list(ShufflesExtended.parse(
     ...         "deal into new stack\\n"
     ...         "cut -2\\n"
     ...         "deal with increment 7\\n"
     ...         "cut 8\\n"
     ...         "cut -4\\n"
     ...         "deal with increment 7\\n"
     ...         "cut 3\\n"
     ...         "deal with increment 9\\n"
     ...         "deal with increment 3\\n"
     ...         "cut -1\\n"
     ... ).get_index_cycle(0, 10))
     [9, 6, 7, 0]
     >>> list(ShufflesExtended.parse(
     ...         "deal into new stack\\n"
     ...         "cut -2\\n"
     ...         "deal with increment 7\\n"
     ...         "cut 8\\n"
     ...         "cut -4\\n"
     ...         "deal with increment 7\\n"
     ...         "cut 3\\n"
     ...         "deal with increment 9\\n"
     ...         "deal with increment 3\\n"
     ...         "cut -1\\n"
     ... ).get_index_cycle(1, 10))
     [2, 5, 4, 1]
     >>> list(ShufflesExtended.parse(
     ...         "deal into new stack\\n"
     ...         "cut -2\\n"
     ...         "deal with increment 7\\n"
     ...         "cut 8\\n"
     ...         "cut -4\\n"
     ...         "deal with increment 7\\n"
     ...         "cut 3\\n"
     ...         "deal with increment 9\\n"
     ...         "deal with increment 3\\n"
     ...         "cut -1\\n"
     ... ).get_index_cycle(3, 10))
     [8, 3]
     """
     if max_count is None:
         max_count = size
     search_index = index
     for step in range(max_count):
         search_index = self.get_index_at_position_after_shuffle(
             search_index, size)
         yield search_index
         if search_index == index:
             break
         debugger.default_report_if("Looking...")
Exemple #8
0
    def step_many(
        self, algorithm: IEAlgorithm, count: int,
        debugger: Debugger = Debugger(enabled=False),
    ) -> "Image":
        """
        >>> _algorithm = IEAlgorithm.from_mapping_text(
        ...     "..#.#..#####.#.#.#.###.##.....###.##.#..###.####..#####..#...."
        ...     "#..#..##..###..######.###...####..#..#####..##..#.#####...##.#"
        ...     ".#..#.##..#.#......#.###.######.###.####...#.##.##..#..#..####"
        ...     "#.....#.#....###..#.##......#.....#..#..#..##..#...##.######.#"
        ...     "###.####.#.#...#.......#..#.#.#...####.##.#......#..#...##.#.#"
        ...     "#..#...##.#.##..###.#......#.#.......#.#.#.####.###.##...#...."
        ...     ".####.#..#..#.##.#....##..#.####....##...##..#...#......#.#..."
        ...     "....#.......##..####..#...#.#.#...##..#.#..###..#####........#"
        ...     "..####......#..#"
        ... )
        >>> image = Image.from_image_text('''
        ...     #..#.
        ...     #....
        ...     ##..#
        ...     ..#..
        ...     ..###
        ... ''')
        >>> print(":", image.step_many(_algorithm, 1))
        : .........
        ..##.##..
        .#..#.#..
        .##.#..#.
        .####..#.
        ..#..##..
        ...##..#.
        ....#.#..
        .........
        >>> print(":", image.step_many(_algorithm, 2))
        : ...........
        ........#..
        ..#..#.#...
        .#.#...###.
        .#...##.#..
        .#.....#.#.
        ..#.#####..
        ...#.#####.
        ....##.##..
        .....###...
        ...........
        """
        result = self
        debugger.default_report(f"Stepping {count} times")
        for step in debugger.stepping(range(count)):
            result = result.step(algorithm)
            debugger.default_report_if(
                f"Stepped {step}/{count} times, {result.light_pixel_count} "
                f"lights in result, size of {tuple(result.boundary.size)}"
            )

        return result
 def apply(
         self,
         reactor: Reactor,
         debugger: Debugger = Debugger(enabled=False),
 ) -> Reactor:
     for step_index, step in debugger.stepping(enumerate(self.steps, 1)):
         step.apply(reactor)
         debugger.default_report_if(
             f"After {step_index} steps: {reactor.cube_count} cubes are on")
     return reactor
Exemple #10
0
    def solve(
            self,
            debugger: Debugger = Debugger(enabled=False),
    ) -> "QuantumGameSearch":
        while not debugger.step_if(self.finished):
            self.advance_once()
            debugger.default_report_if(
                f"Done {self.move_count} moves, with "
                f"{len(self.residual_state_counts)} remaining states, "
                f"currently {self.player_1_wins} vs {self.player_2_wins}")

        return self
 def get_next_password(
         self,
         debugger: Debugger = Debugger(enabled=False),
 ) -> 'Password':
     """
     >>> Password('abcdefgh').get_next_password()
     'abcdffaa'
     >>> Password('ghijklmn').get_next_password()
     'ghjaabcc'
     """
     debugger.reset()
     for password in debugger.stepping(self.get_next_password_candidates()):
         if password.is_valid():
             return password
         debugger.default_report_if(password)
Exemple #12
0
    def apply(
            self,
            step_set: RebootStepSet,
            debugger: Debugger = Debugger(enabled=False),
    ) -> "RegionSet":
        region_class = self.get_region_class()
        for index, step in debugger.stepping(enumerate(step_set.steps, 1)):
            step_region = region_class.from_step(step)
            if step.set_to_on:
                self.add(step_region)
            else:
                self.remove(step_region)
            debugger.default_report_if(
                f"Done {index}/{len(step_set.steps)}, "
                f"{len(self.regions)} regions, {len(self)} total cubes")

        return self
 def get_lowest_index_with_zeros(
     self,
     start: int = 1,
     zero_count: int = 5,
     debugger: Debugger = Debugger(enabled=False)) -> int:
     """
     >>> Hasher("abcdef").get_lowest_index_with_zeros()
     609043
     >>> Hasher("pqrstuv").get_lowest_index_with_zeros()
     1048970
     """
     prefix = '0' * zero_count
     debugger.reset()
     for index in debugger.stepping(count(start)):
         if self.does_index_give_hash_prefix(index, prefix):
             return index
         debugger.default_report_if(index)
Exemple #14
0
    def get_code(
            self,
            index: int,
            debugger: Debugger = Debugger(enabled=False),
    ) -> int:
        """
        >>> list(map(Grid().get_code, range(1, 5)))
        [20151125, 31916031, 18749137, 16080970]
        """
        max_precomputed_index = self.get_max_precomputed_index(index)
        code = self.pre_computed_codes[max_precomputed_index]
        for computing_index \
                in debugger.stepping(range(index - max_precomputed_index)):
            debugger.default_report_if(computing_index)
            code *= self.multiplier
            code %= self.modulo

        return code
Exemple #15
0
 def apply(
     self,
     matrix: Optional[MatrixT] = None,
     debugger: Debugger = Debugger(enabled=False)
 ) -> MatrixT:
     """
     >>> InstructionSet.from_instructions_text(
     ...     "turn on 0,0 through 999,999").apply().get_brightness_total()
     2000000
     """
     if matrix is None:
         matrix_class = self.get_matrix_class()
         matrix = matrix_class()
     debugger.reset()
     for instruction in debugger.stepping(self.instructions):
         instruction.apply(matrix)
         debugger.default_report_if()
     return matrix
Exemple #16
0
    def find_min_mana_necessary(
            self,
            debugger: Debugger = Debugger(enabled=False),
    ) -> int:
        def reporting_format(_: Debugger, message: str) -> str:
            if min_mana_spent is None:
                min_mana_spent_str = "no winner yet"
            else:
                min_mana_spent_str = f"best is {min_mana_spent}"
            return f"{message} ({min_mana_spent_str}, {len(stack)} in stack)"

        with debugger.adding_extra_report_format(reporting_format):
            stack = [deepcopy(self)]
            min_mana_spent = None
            min_mana_game = None
            debugger.default_report_if("Searching for a winning game...")
            while debugger.step_if(stack):
                debugger.default_report_if("Searching for a winning game...")
                game = stack.pop(0)
                if min_mana_spent is not None \
                        and game.player.mana_spent >= min_mana_spent:
                    continue
                next_games = game.get_next_games(debugger)
                for next_game in next_games:
                    if (min_mana_spent is not None
                            and next_game.player.mana_spent >= min_mana_spent):
                        continue
                    if next_game.winner == CharacterEnum.Player:
                        min_mana_spent = next_game.player.mana_spent
                        min_mana_game = next_game
                        debugger.report(f"Better game found: {min_mana_spent}")
                    stack.append(next_game)

            debugger.default_report(f"Finished searching")

        if min_mana_spent is None:
            raise Exception(f"Could not find a winning game")

        options_played_str = ', '.join(
            option.name for option in min_mana_game.options_played
            if isinstance(option, SpellEnum))
        debugger.report(f"Min mana game moves: {options_played_str}")

        return min_mana_spent
    def measure_distances(
            self,
            debugger: Debugger = Debugger(enabled=False),
    ) -> None:
        while debugger.step_if(self.stack):
            should_report = debugger.should_report()
            debugger.default_report_if(
                f"Seen {len(self.distances)}, {len(self.stack)} in stack, "
                f"target risk is {self.distances.get(self.target)}")
            if should_report:
                debugger.report(str(self))
            state = self.stack.pop(0)
            if state.distance > self.distances[state.position]:
                continue

            for next_state in state.get_next_states(self):
                self.visit_state(next_state)
        if debugger.enabled:
            debugger.report(str(self))
def get_message_after_index(
        initial: str,
        debugger: Debugger = Debugger(enabled=False),
) -> str:
    """
    >>> get_message_after_index("03036732577212944063491565474664")
    84462026
    """
    start_index = int(initial[:7])
    original_length = len(initial)
    length = original_length * 10000
    skip_lengths_count = math.floor(start_index / original_length)
    lengths_count = int(length / original_length - skip_lengths_count)
    skipped_phase = list(map(int, initial)) * lengths_count
    skipped_offset = start_index - skip_lengths_count * original_length
    skipped_phase = skipped_phase[skipped_offset:]
    result = skipped_phase
    debugger.default_report(f"Looking for message skipping {start_index}")
    for _ in debugger.stepping(range(100)):
        result = get_next_phase_after_index(result, start_index)
        debugger.default_report_if(f"So far: {''.join(map(str, result[:8]))}")
    return "".join(map(str, result[:8]))
Exemple #19
0
def get_next_phase(
        phase: np.ndarray,
        length: int,
        phase_patterns: Optional[List[np.ndarray]] = None,
        debugger: Debugger = Debugger(enabled=False),
) -> List[int]:
    """
    >>> "".join(map(str, get_next_phase(np.array(list(map(int, '12345678'))), 8)))
    '48226158'
    >>> "".join(map(str, get_next_phase(np.array(list(map(int, '48226158'))), 8)))
    '34040438'
    >>> "".join(map(str, get_next_phase(np.array(list(map(int, '34040438'))), 8)))
    '03415518'
    >>> "".join(map(str, get_next_phase(np.array(list(map(int, '03415518'))), 8)))
    '01029498'
    """
    # if phase_patterns is None:
    #     phase_patterns = get_phase_patterns(length)
    if phase_patterns is None:
        indexes_and_phase_patterns = zip_longest(
            range(length),
            [],
            fillvalue=None,
        )
    else:
        indexes_and_phase_patterns = enumerate(phase_patterns)

    next_phase = []
    for index, phase_pattern in debugger.stepping(indexes_and_phase_patterns):
        next_phase.append(
            get_element_for_next_phase(phase,
                                       length,
                                       index,
                                       phase_pattern=phase_pattern))
        debugger.default_report_if(
            f"{index}/{length} ({index * 100 // length}%)")

    return next_phase
    def find_scanners_positions(
        self,
        debugger: Debugger = Debugger(enabled=False),
    ) -> List[Tuple[BeaconT, ScannerT]]:
        """
        >>> # noinspection PyUnresolvedReferences
        >>> [_position for _position, _ in Scanner2DSet.from_scanners_text('''
        ...     --- scanner 0 ---
        ...     0,2
        ...     4,1
        ...     3,3
        ...
        ...     --- scanner 1 ---
        ...     -1,-1
        ...     -5,0
        ...     -2,1
        ... ''').find_scanners_positions()]
        [Beacon2D(x=0, y=0), Beacon2D(x=5, y=2)]
        """
        if not self.scanners:
            return []

        beacon_class = self.get_beacon_class()
        first_scanner = self.scanners[0]
        positions_and_scanners_by_scanner: Dict[int, Tuple[BeaconT, ScannerT]] \
            = {
                id(first_scanner):
                (beacon_class.get_zero_point(), first_scanner)
            }
        found_scanners = [first_scanner]
        remaining_scanners = self.scanners[1:]
        debugger.default_report(
            f"Looking for {len(self.scanners) - 1} positions, found "
            f"{len(found_scanners) - 1}")
        while remaining_scanners:
            for other_index, other in enumerate(remaining_scanners):
                for found_index, found_scanner \
                        in debugger.step_if(enumerate(found_scanners)):
                    debugger.default_report_if(
                        f"Looking for {len(self.scanners) - 1} positions, "
                        f"found {len(found_scanners) - 1}")
                    found_position, found_reoriented = \
                        positions_and_scanners_by_scanner[id(found_scanner)]
                    position_and_scanner = \
                        found_reoriented.find_other_scanner_position(
                            other, self.min_overlap,
                        )
                    if not position_and_scanner:
                        continue

                    position, reoriented = position_and_scanner
                    position = position.offset(found_position)
                    found_scanners.append(other)
                    positions_and_scanners_by_scanner[id(other)] = \
                        position, reoriented
                    remaining_scanners.remove(other)
                    break
                else:
                    continue

                break
            else:
                raise Exception(f"Could not find any remaining scanner "
                                f"({len(remaining_scanners)} remaining out of "
                                f"{len(self.scanners)})")

        return [
            positions_and_scanners_by_scanner[id(scanner)]
            for scanner in self.scanners
        ]