# Principled Programming / Tim Teitelbaum / Chapter 17. from mrp import MRP import random class RunMaze: """# Rat running. See Chapter 15 of text.""" # CLIENT CODE UNIQUE TO DEPTH-FIRST SEARCH SOLUTION @classmethod def _solve(cls) -> None: """Compute a direct path through the maze, if one exists.""" MRP.search() # LEGACY CLIENT CODE (Chapter 15) @classmethod def main(cls) -> None: """Run a maze given as input, if possible.""" # Input a maze of arbitrary size, or output “malformed input” # and stop if the input is improper. Input format: TBD. RunMaze._input() # Compute a direct path through the maze, if one exists. RunMaze._solve() # Output the direct path found, or “unreachable” if there is # none. Output format: TBD. RunMaze._output() # Stop execution if path found is not a solution. assert MRP.is_solution(), "internal program error" @classmethod def _input(cls) -> None: """# Input a maze of arbitrary size, or output “malformed input” and stop if the input is improper. """ MRP.input() @classmethod def _output(cls) -> None: """Output the direct path found, or “unreachable” if there is none.""" if not(MRP.is_at_cheese()): print ("Unreachable") else: MRP.print_maze() @classmethod def exhaustive_test(cls) -> None: """Generate/solve all mazes of sizes up through 3, and validate paths found.""" for N in range(1, 5): for w in range(0, 2 ** (2 * N *(N - 1))): MRP.generate_input(N, w) RunMaze._solve() assert MRP.is_solution(), "internal program error" if (w > 0) and (w%100000 == 0): print(w) # Heartbeat. print("passed for size:", N) print("passed") @classmethod def fuzz_test(cls, f: int, n: int) -> None: """Fuzz F mazes of size N.""" for k in range(0, f): RunMaze.random_test(n) @classmethod def random_test(cls, n: int) -> None: """Create a random maze of size N.""" # Let w be random walls for the N-by-N maze. w = random.randint(0, 2 ** (2 * n * (n - 1))) # Generate maze of size N with walls w, solve, and validate (or abort). print("Size:", n, "Walls:", w) # (Comment out for serious test.) MRP.generate_input(n, w) # Create N-by-N maze with walls w. RunMaze._solve() # Attempt a solution. assert MRP.is_solution() # Validate solution (or abort). MRP.print_maze() # (Comment out for serious test.) # Uncomment to run on builtin example. RunMaze.main() # Uncomment to run on all mazes of size <= 4. #RunMaze.exhaustive_test() # Uncomment to run on 25 random mazes of size 5. #RunMaze.fuzz_test(25, 5)