import heapq

def manhattan(a, b):
    return abs(a.x - b.x) + abs(a.y - b.y)

class AStarStrategy:
    def find_path(self, maze, start, exit_):
        g = {start: 0}
        parent = {start: None}

        counter = 0
        open_heap = [(0, counter, start)]
        in_open = {start}
        visited = set()

        while open_heap:
            _, _, cur = heapq.heappop(open_heap)
            in_open.discard(cur)
            visited.add(cur)

            if cur == exit_:
                return self._reconstruct(parent, start, exit_), visited

            for n in maze.get_neighbors(cur):
                tentative = g[cur] + 1
                if tentative < g.get(n, float('inf')):
                    g[n] = tentative
                    parent[n] = cur
                    f = tentative + manhattan(n, exit_)
                    if n not in in_open:
                        counter += 1
                        heapq.heappush(open_heap, (f, counter, n))
                        in_open.add(n)

        return None, visited

    def _reconstruct(self, parent, start, exit_):
        path = []
        cur = exit_
        while cur:
            path.append(cur)
            cur = parent[cur]
        return list(reversed(path))
