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
Beispiel #2
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]))
Beispiel #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
Beispiel #4
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
Beispiel #5
0
    def find_first_synchronised_flash_step_index(
            self,
            debugger: Debugger = Debugger(enabled=False),
    ) -> int:
        """
        >>> GridExtended.from_grid_text('''
        ...     5483143223
        ...     2745854711
        ...     5264556173
        ...     6141336146
        ...     6357385478
        ...     4167524645
        ...     2176841721
        ...     6882881134
        ...     4846848554
        ...     5283751526
        ... ''').find_first_synchronised_flash_step_index()
        195
        """
        grid = deepcopy(self)
        for step_index in debugger.stepping(count(1)):
            debugger.report_if(step_index)
            grid.step()
            if grid.did_all_flash:
                return step_index

        raise Exception("Run out of numbers!")
    def get_all_possible_chains_to_target(
        self,
        start: str,
        target: str,
        allow_reverse: bool = True,
        debugger: Debugger = Debugger(enabled=False),
    ) -> Iterable[Tuple[str, ...]]:
        """
        >>> list(MachineExtended().get_all_possible_chains_to_target(
        ...     "a", "b", allow_reverse=False))
        []
        >>> list(MachineExtended({'H': ['O']})
        ...      .get_all_possible_chains_to_target(
        ...         "HH", "OO", allow_reverse=False))
        [('HH', 'OH', 'OO'), ('HH', 'HO', 'OO')]
        >>> list(MachineExtended({'H': ['OH']})
        ...      .get_all_possible_chains_to_target(
        ...         "HH", "OHOH", allow_reverse=False))
        [('HH', 'OHH', 'OHOH'), ('HH', 'HOH', 'OHOH')]
        >>> list(MachineExtended({'H': ['O'], 'O': ['H']})
        ...      .get_all_possible_chains_to_target(
        ...         "HH", "OH", allow_reverse=False))
        [('HH', 'OH'), ('HH', 'HO', 'OO', 'OH')]
        >>> list(MachineExtended({'OH': ['H']})
        ...      .get_all_possible_chains_to_target(
        ...         "OHOH", "HH", allow_reverse=False))
        [('OHOH', 'HOH', 'HH'), ('OHOH', 'OHH', 'HH')]
        >>> list(MachineExtended().get_all_possible_chains_to_target("a", "b"))
        []
        >>> list(MachineExtended({'H': ['O']})
        ...      .get_all_possible_chains_to_target("HH", "OO"))
        [('HH', 'OH', 'OO'), ('HH', 'HO', 'OO')]
        >>> list(MachineExtended({'H': ['OH']})
        ...      .get_all_possible_chains_to_target("HH", "OHOH"))
        [('OHOH', 'HOH', 'HH'), ('OHOH', 'OHH', 'HH')]
        >>> list(MachineExtended({'H': ['O'], 'O': ['H']})
        ...      .get_all_possible_chains_to_target("HH", "OH"))
        [('HH', 'OH'), ('HH', 'HO', 'OO', 'OH')]
        """
        if len(target) < len(start):
            if self.are_substitutions_not_decreasing():
                raise Exception(
                    f"Cannot go from length {len(start)} to length "
                    f"{len(target)}, as substitutions don't decrease")
        elif len(target) > len(start):
            if self.are_substitutions_not_increasing():
                raise Exception(
                    f"Cannot go from length {len(start)} to length "
                    f"{len(target)}, as substitutions don't increase")
        if allow_reverse:
            if len(target) > len(start):
                yield from self.reverse().get_all_possible_chains_to_target(
                    start=target, target=start, debugger=debugger)
                return
        prune = self.get_prune(target)

        for chain in debugger.stepping(
                self.get_all_possible_chains(start, prune, debugger=debugger)):
            if chain[-1] == target:
                yield chain
Beispiel #7
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
 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)
    def step_many(self, step_count: Optional[int] = None,
                  debugger: Debugger = Debugger(enabled=False)):
        if step_count is None:
            steps = count()
        else:
            steps = range(step_count)
        debugger.reset()
        for _ in debugger.stepping(steps):
            self.step()
            if self.has_finished():
                break
            if debugger.should_report():
                debugger.default_report(
                    f"remaining: {len(self.get_remaining_positions())}, "
                    f"position: {self.position}")

        return self
    def step_many(
        self,
        sequence: str,
        step_count: int = 40,
        debugger: Debugger = Debugger(enabled=False)) -> str:
        """
        >>> LookAndSay().step_many("1", 5)
        '312211'
        """
        debugger.reset()
        result = sequence
        for step in debugger.stepping(range(step_count)):
            result = self.step(result)
            if debugger.should_report():
                debugger.default_report(f"step {step}/{step_count}")

        return result
 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)
Beispiel #13
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
Beispiel #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
Beispiel #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
    def get_minimum_step_count(
            self,
            start: int = 0,
            return_to_start: bool = False,
            debugger: Debugger = Debugger(enabled=False),
    ) -> int:
        """
        >>> Graph({
        ...     (0, 1): 2, (1, 0): 2,
        ...     (0, 4): 2, (4, 0): 2,
        ...     (1, 2): 6, (2, 1): 6,
        ...     (2, 3): 2, (3, 2): 2,
        ...     (3, 4): 8, (4, 3): 8,
        ... }).get_minimum_step_count()
        14
        """
        nodes = self.get_nodes()
        if start not in nodes:
            raise Exception(f"Start {start} is not in nodes {nodes}")
        other_nodes = set(nodes) - {start}
        prefix = (start, )
        if return_to_start:
            suffix = prefix
        else:
            suffix = ()
        visit_orders = (prefix + permutation + suffix
                        for permutation in itertools.permutations(other_nodes))
        min_distance = None
        trip_distances_cache = {}
        for visit_order in debugger.stepping(visit_orders):
            distance = sum(
                self.get_shortest_distance(
                    node_a,
                    node_b,
                    nodes,
                    trip_distances_cache=trip_distances_cache)
                for node_a, node_b in get_windows(visit_order, 2))
            if min_distance is None or distance < min_distance:
                min_distance = distance
            if debugger.should_report():
                debugger.default_report(f"min distance: {min_distance}")

        return min_distance
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]))
Beispiel #18
0
 def get_min_house_number_with_at_least_present_count(
     self,
     min_present_count: int,
     debugger: Debugger = Debugger(enabled=False)
 ) -> int:
     """
     >>> Santa().get_min_house_number_with_at_least_present_count(100)
     6
     """
     max_present_count_seen = None
     debugger.reset()
     for house_number in debugger.stepping(count(1)):
         present_count = self.get_house_present_count(house_number)
         if present_count >= min_present_count:
             return house_number
         if max_present_count_seen is None \
                 or present_count > max_present_count_seen:
             max_present_count_seen = present_count
         if debugger.should_report():
             debugger.default_report(
                 f"max presents: {max_present_count_seen}"
                 f"/{min_present_count}")
Beispiel #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