예제 #1
0
    def solve(self, building: BuildingT, debug: bool = False
              ) -> List[BuildingT]:
        if building.is_complete():
            return []
        previous_map: Dict[BuildingT, BuildingT] = {building: None}
        stack: List[Tuple[int, BuildingT]] = [(0, building)]
        if debug:
            timer = Timer()
        for step in count():
            if not stack:
                break
            distance, current_building = stack.pop(0)
            next_buildings = self.get_next_states(current_building)
            next_buildings -= set(previous_map)
            next_distance = distance + 1
            for next_building in next_buildings:
                previous_map[next_building] = current_building
                if next_building.is_complete():
                    return self.map_solution(previous_map, next_building)
                stack.append((next_distance, next_building))

            if debug:
                if step % 5000 == 0:
                    # noinspection PyUnboundLocalVariable
                    print(
                        f"Step {step}, time: "
                        f"{timer.get_pretty_current_duration(0)}s, stack: "
                        f"{len(stack)}, seen: {len(previous_map)}, "
                        f"distance: {distance}")

        raise Exception(f"Cannot find a solution")
    def solve(self, debug: bool = False) -> int:
        if self.optimised_building.is_complete():
            return 0
        seen = {self.optimised_building}
        stack: List[Tuple[int, OptimisedBuildingT]] = [
            (0, self.optimised_building),
        ]
        if debug:
            timer = Timer()
        for step in count():
            if not stack:
                break
            distance, current_building = stack.pop(0)
            next_buildings = self.get_next_states(current_building)
            next_buildings -= seen
            next_distance = distance + 1
            for next_building in next_buildings:
                seen.add(next_building)
                if next_building.is_complete():
                    return next_distance
                stack.append((next_distance, next_building))

            if debug:
                if step % 5000 == 0:
                    # noinspection PyUnboundLocalVariable
                    print(f"Step {step}, time: "
                          f"{timer.get_pretty_current_duration(0)}, stack: "
                          f"{len(stack)}, seen: {len(seen)}, distance: "
                          f"{distance}")

        raise Exception(f"Cannot find a solution")
예제 #3
0
    def solve(self,
              maze: 'Maze',
              start: Position,
              end: Position,
              debug: bool = False) -> List[Position]:
        """
        >>> _maze = Maze(10).fill(product(range(10), range(7)))
        >>> solution = MazeSolver().solve(_maze, Point2D(1, 1), Point2D(7, 4))
        >>> print(_maze.show(solution=solution))
        .#.####.##
        .O#..#...#
        #OOO.##...
        ###O#.###.
        .##OO#.O#.
        ..##OOOO#.
        #...##.###
        >>> bare_maze = Maze(10)
        >>> bare_solution = MazeSolver().solve(
        ...     bare_maze, Point2D(1, 1), Point2D(7, 4))
        >>> bare_solution
        [Point2D(x=1, y=1), Point2D(x=1, y=2), Point2D(x=2, y=2),
            Point2D(x=3, y=2), Point2D(x=3, y=3), Point2D(x=3, y=4),
            Point2D(x=4, y=4), Point2D(x=4, y=5), Point2D(x=5, y=5),
            Point2D(x=6, y=5), Point2D(x=7, y=5), Point2D(x=7, y=4)]
        """
        if start == end:
            return [start]
        stack = [start]
        previous = {start: None}
        if debug:
            step = 0
            timer = Timer()
        while stack:
            position = stack.pop(0)
            neighbours = position.get_manhattan_neighbours()
            for neighbour in neighbours:
                if not maze.is_position_valid(neighbour):
                    continue
                if neighbour in previous:
                    continue
                if maze.get(neighbour):
                    continue
                previous[neighbour] = position
                if neighbour == end:
                    return self.get_solution(end, previous)
                stack.append(neighbour)

            if debug:
                step += 1
                if step % 1000 == 0:
                    print(f"Step: {step}, time: "
                          f"{timer.get_pretty_current_duration(0)}, seen: "
                          f"{len(previous)}, stack: {len(stack)}")
    def double_solve(self, debug: bool = False) -> int:
        if self.optimised_building.is_complete():
            return 0
        distances_from_start = {self.optimised_building: 0}
        distances_from_end = {self.complete_optimised_building: 0}
        stack_from_start: List[Tuple[int, OptimisedBuildingT]] = [
            (0, self.optimised_building),
        ]
        stack_from_end: List[Tuple[int, OptimisedBuildingT]] = [
            (0, self.complete_optimised_building),
        ]
        searches = [
            (stack_from_start, distances_from_start, distances_from_end),
            (stack_from_end, distances_from_end, distances_from_start),
        ]
        if debug:
            timer = Timer()
        for step in count():
            if not stack_from_start or not stack_from_end:
                break
            for stack, distances, other_distances in searches:
                distance, current_building = stack.pop(0)
                next_buildings = self.get_next_states(current_building)
                next_buildings -= set(distances)
                next_distance = distance + 1
                for next_building in next_buildings:
                    if next_building in other_distances:
                        return (next_distance +
                                other_distances[next_building] - 1)
                    distances[next_building] = next_distance
                    stack.append((next_distance, next_building))

            if debug:
                if step % 5000 == 0:
                    # noinspection PyUnboundLocalVariable
                    print(
                        f"Step {step}, time: "
                        f"{timer.get_pretty_current_duration(0)}, stack: "
                        f"{len(stack)}, seen: "
                        f"{len(distances_from_start) + len(distances_from_end)}"
                        f", distance: {distance}")

        raise Exception(f"Cannot find a solution")
예제 #5
0
    def run_challenge(self, year, day, part, force, debug, debug_interval):
        challenge_instance = self.get_or_create_challenge(
            year, day, part, force)
        if not challenge_instance:
            return False, None
        with Timer() as timer:
            debugger = Debugger(enabled=debug,
                                min_report_interval_seconds=debug_interval)
            if has_method_arguments(challenge_instance.default_solve,
                                    "debugger"):
                solution = challenge_instance.default_solve(debugger=debugger)
            else:
                solution = challenge_instance.default_solve(debug=debugger)
        if solution is None:
            styled_solution = e_error(str(solution))
        else:
            styled_solution = e_value(str(solution))
        click.echo(f"Solution: {styled_solution}"
                   f" (in {timer.get_pretty_duration(2)})")

        return True, solution
    def get_keys(self,
                 _count: Optional[int] = 64,
                 start: int = 0,
                 window_size: int = 1000,
                 debug: bool = False) -> Iterable[int]:
        windows = get_windows(self.get_all_hashes(start), window_size + 1)
        key_count = 0
        if debug:
            timer = Timer()
        for index, window in enumerate(windows):
            _hash, next_hashes = window[0], window[1:]
            if self.is_hash_a_key(_hash, next_hashes):
                key_count += 1
                yield key_count, index, _hash
                if _count is not None and key_count >= _count:
                    break

            if debug:
                if index % 1000 == 0:
                    print(f"Count: {index}, time: "
                          f"{timer.get_pretty_current_duration()}, key count: "
                          f"{key_count}/{_count}")
예제 #7
0
    def test_challenge(self, year, day, part, force, filters_texts):
        challenge_instance = self.get_or_create_challenge(
            year, day, part, force)
        if not challenge_instance:
            return None
        filters_text = " ".join(filters_texts)
        test_modules = challenge_instance.get_test_modules()
        with Timer() as timer:
            modules_and_results = [
                (module,
                 testmod_with_filter(
                     module,
                     optionflags=challenge_instance.optionflags,
                     filters_text=filters_text)) for module in test_modules
            ]
        results = TestResults(
            attempted=sum(result.attempted
                          for _, result in modules_and_results),
            failed=sum(result.failed for _, result in modules_and_results),
        )
        failed_modules = [
            module.__name__ if module else 'main'
            for module, result in modules_and_results if result.failed
        ]
        if failed_modules:
            click.echo(
                f"{e_error(f'{results.failed}/{results.attempted} tests')} "
                f"in {len(failed_modules)}/{len(test_modules)} modules "
                f"{e_error('failed')} "
                f"in {timer.get_pretty_duration(2)}"
                f": {e_error(', '.join(failed_modules))}")
        else:
            click.echo(f"{results.attempted} tests "
                       f"in {len(test_modules)} modules "
                       f"{e_success('passed')} "
                       f"in {timer.get_pretty_duration(2)}")

        return results
예제 #8
0
    def flood(self,
              maze: part_a.Maze,
              start: part_a.Position,
              depth: int,
              debug: bool = False) -> Set[part_a.Position]:
        if depth <= 0:
            maze.get(start)
            return {start}
        stack = [(0, start)]
        seen = {start}
        if debug:
            step = 0
            timer = Timer()
        while stack:
            distance, position = stack.pop(0)
            next_distance = distance + 1
            neighbours = position.get_manhattan_neighbours()
            for neighbour in neighbours:
                if not maze.is_position_valid(neighbour):
                    continue
                if neighbour in seen:
                    continue
                if maze.get(neighbour):
                    continue
                seen.add(neighbour)
                if next_distance >= depth:
                    continue
                stack.append((next_distance, neighbour))

            if debug:
                step += 1
                if step % 1000 == 0:
                    print(f"Step: {step}, time: "
                          f"{timer.get_pretty_current_duration(0)}, seen: "
                          f"{len(seen)}, stack: {len(stack)}")
                    print(maze.show(solution=seen))

        return seen
    def apply_stream(
        self,
        state: Optional[State] = None,
        debug: bool = False,
    ) -> Iterable[State]:
        if state is None:
            state = State()
        if debug:
            timer = Timer()
        step = 0
        while 0 <= state.program_counter < len(self.instructions):
            instruction = self.instructions[state.program_counter]
            instruction.apply(state)
            if debug:
                if step % 10000000 == 0:
                    # noinspection PyUnboundLocalVariable
                    print(
                        f"Step {step}, time: "
                        f"{timer.get_pretty_current_duration(0)}, "
                        f"values: {state.values}, pc: {state.program_counter}")
            step += 1
            yield state

        return state