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")
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")
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}")
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
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