class Cell:
    def __init__(self, row, col, value):
        self.row = row
        self.col = col
        self.value = value

    def is_wall(self):
        return self.value == "#"

    def is_start(self):
        return self.value == "S"

    def is_finish(self):
        return self.value == "F"


class Maze:
    def __init__(self, cells, start, finish):
        self.cells = cells
        self.start = start
        self.finish = finish
        self.height = len(cells)
        self.width = len(cells[0]) if cells else 0

    def inside(self, row, col):
        return 0 <= row < self.height and 0 <= col < self.width

    def get_cell(self, row, col):
        if not self.inside(row, col):
            return None
        return self.cells[row][col]

    def is_free(self, row, col):
        cell = self.get_cell(row, col)
        return cell is not None and not cell.is_wall()

    def neighbors(self, row, col):
        variants = [
            (row - 1, col),
            (row + 1, col),
            (row, col - 1),
            (row, col + 1)
        ]
        result = []
        for next_row, next_col in variants:
            if self.is_free(next_row, next_col):
                result.append((next_row, next_col))
        return result

    def draw(self, path=None):
        path_set = set(path) if path else set()
        lines = []
        for row in range(self.height):
            line = ""
            for col in range(self.width):
                cell = self.cells[row][col]
                if (row, col) in path_set and not cell.is_start() and not cell.is_finish():
                    line += "*"
                else:
                    line += cell.value
            lines.append(line)
        return "\n".join(lines)


class MazeBuilder:
    def __init__(self):
        self.lines = []

    def from_file(self, filename):
        with open(filename, "r", encoding="utf-8") as file:
            self.lines = [line.rstrip("\n") for line in file if line.strip()]
        return self

    def build(self):
        cells = []
        start = None
        finish = None
        width = len(self.lines[0])

        for row, line in enumerate(self.lines):
            if len(line) != width:
                raise ValueError("maze lines have different length")
            cell_row = []
            for col, value in enumerate(line):
                cell = Cell(row, col, value)
                if cell.is_start():
                    start = (row, col)
                if cell.is_finish():
                    finish = (row, col)
                cell_row.append(cell)
            cells.append(cell_row)

        if start is None or finish is None:
            raise ValueError("maze must have start and finish")

        return Maze(cells, start, finish)