Skip to content

Instantly share code, notes, and snippets.

@mrh1997
Created October 21, 2019 17:58
Show Gist options
  • Save mrh1997/c93d1995a3c1bf6694b87ecd3a2a9c21 to your computer and use it in GitHub Desktop.
Save mrh1997/c93d1995a3c1bf6694b87ecd3a2a9c21 to your computer and use it in GitHub Desktop.
Mouse Searches Cheese in Labyrinth
from typing import NamedTuple, Optional
from enum import Enum
class Dir(Enum):
Up = 0
Right = 1
Down = 2
Left = 3
REVERSE_DIR_MAP = {
Dir.Up: Dir.Down,
Dir.Right: Dir.Left,
Dir.Down: Dir.Up,
Dir.Left: Dir.Right
}
class Coordinate(NamedTuple):
y:int
x:int
def goto(self, dir):
if dir == Dir.Up:
return Coordinate(self.y - 1, self.x)
elif dir == Dir.Right:
return Coordinate(self.y, self.x + 1)
elif dir == Dir.Down:
return Coordinate(self.y + 1, self.x)
elif dir == Dir.Left:
return Coordinate(self.y, self.x - 1)
class Maze:
def __init__(self, maze:str):
self.maze = [l.strip() for l in maze.strip().splitlines()]
def can_goto(self, coord:Coordinate, dir:Dir):
if dir == Dir.Up:
return self.maze[coord.y-1][coord.x] not in ('_', 'L')
elif dir == Dir.Right:
return self.maze[coord.y][coord.x+1] not in ('|', 'L')
elif dir == Dir.Down:
return self.maze[coord.y][coord.x] not in ('_', 'L')
elif dir == Dir.Left:
return self.maze[coord.y][coord.x] not in ('|', 'L')
@property
def height(self):
return len(self.maze)
@property
def width(self):
return len(self.maze[0])
class Mouse:
def __init__(self, maze:Maze, start:Coordinate):
self.maze = maze
self.coord = start
self.enter_dir = None
self.memory = [[None]*maze.width for i in range(maze.height)]
self.memory[start.y][start.x] = Dir.Down # mark as visited
def get_first_visit(self, coord:Coordinate) -> Optional[Dir]:
return self.memory[coord.y][coord.x]
def move(self) -> Dir:
free_dirs = [ dir for dir in Dir if self.maze.can_goto(self.coord,dir) ]
unvisited_dirs = [ dir for dir in free_dirs
if not self.get_first_visit(self.coord.goto(dir)) ]
if unvisited_dirs:
dir = self.enter_dir = unvisited_dirs.pop()
self.coord = self.coord.goto(dir)
self.memory[self.coord.y][self.coord.x] = REVERSE_DIR_MAP[dir]
else:
dir = self.get_first_visit(self.coord)
self.coord = self.coord.goto(dir)
return dir
if __name__ == '__main__':
maze = Maze("""
___________
| L__ | |
|||___ ||||
L__ L____||
L_________|
""")
cheese = Coordinate(2, 1)
mouse = Mouse(maze, Coordinate(1, 0))
while mouse.coord != cheese:
dir = mouse.move()
print(f"{dir:10} => {mouse.coord}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment