from typing import List, Optional

class Cell:
    def __init__(self, x: int, y: int, wall: bool = False, 
                 start: bool = False, exit: bool = False):
        self.x = x
        self.y = y
        self.is_wall = wall
        self.is_start = start
        self.is_exit = exit
        self.prev = None 
    
    def passable(self) -> bool:
        return not self.is_wall
    
    def __str__(self):
        if self.is_start: return 'S'
        if self.is_exit: return 'E'
        if self.is_wall: return '#'
        return ' '
    
    def __eq__(self, other):
        return isinstance(other, Cell) and self.x == other.x and self.y == other.y
    
    def __hash__(self):
        return hash((self.x, self.y))

class Maze:
    def __init__(self, w: int, h: int):
        self.width = w
        self.height = h
        self.grid = [[Cell(x, y) for x in range(w)] for y in range(h)]
        self.start_cell = None
        self.exit_cell = None
    
    def cell_at(self, x: int, y: int) -> Optional[Cell]:
        if 0 <= x < self.width and 0 <= y < self.height:
            return self.grid[y][x]
        return None
    
    def neighbors(self, cell: Cell) -> List[Cell]:
        result = []
        for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            neighbor = self.cell_at(cell.x + dx, cell.y + dy)
            if neighbor and neighbor.passable():
                result.append(neighbor)
        return result
    
    def __str__(self):
        return '\n'.join(''.join(str(c) for c in row) for row in self.grid)