### BUGGY CODE ###

from heapq import heappush, heappop
from itertools import count


def _dijkstra(G, source, weight, pred=None, paths=None, cutoff=None, target=None):
    return _dijkstra_multisource(
        G, [source], weight, pred=pred, paths=paths, cutoff=cutoff, target=target
    )


def _dijkstra_multisource(
    G, sources, weight, pred=None, paths=None, cutoff=None, target=None):
    G_succ = G._succ if G.is_directed() else G._adj

    push = heappush
    pop = heappop
    dist = {}  # dictionary of final distances
    seen = {}
    # fringe is heapq with 3-tuples (distance,c,node)
    # use the count c to avoid comparing nodes (may not be able to)
    c = count()
    fringe = []
    for source in sources:
        if source not in G:
            raise KeyError
        seen[source] = 0
        push(fringe, (0, next(c), source))
    while fringe:
        (d, _, v) = pop(fringe)
        if v in dist:
            continue  # already searched this node.
        dist[v] = d
        if v == target:
            break
        for u, e in G_succ[v].items():
            cost = weight(v, u, e)
            if cost is None:
                continue
            vu_dist = dist[v] + cost
            if cutoff is not None:
                if vu_dist > cutoff:
                    continue
            if u in dist:
                u_dist = dist[u]
                if vu_dist < u_dist:
                    raise ValueError("Contradictory paths found:", "negative weights?")
                elif pred is not None and vu_dist == u_dist:
                    pred[u].append(v)
            elif u not in seen or vu_dist < seen[u]:
                seen[u] = vu_dist
                push(fringe, (vu_dist, next(c), u))
                if paths is not None:
                    paths[u] = paths[v] + [u]
                if pred is not None:
                    pred[u] = [v]
            elif vu_dist == seen[u]:
                if pred is not None:
                    pred[u].append(v)
    return dist


def dijkstra_path_length(G, source, target, weight="weight"):
    
    if source == target:
        return 0
    weight = _weight_function(G, weight)
    length = _dijkstra(G, source, weight, target=target)
    try:
        return length[target]
    except KeyError:
        raise KeyError


def _weight_function(G, weight):
    if callable(weight):
        return weight
    if G.is_multigraph():
        return lambda u, v, d: min(attr.get(weight, 1) for attr in d.values())
    return lambda u, v, data: data.get(weight, 1)


class Graph:
    node_dict_factory = dict
    node_attr_dict_factory = dict
    adjlist_outer_dict_factory = dict
    adjlist_inner_dict_factory = dict
    edge_attr_dict_factory = dict
    graph_attr_dict_factory = dict
    
    def __init__(self, incoming_graph_data=None, **attr):
        
        self.graph_attr_dict_factory = self.graph_attr_dict_factory
        self.node_dict_factory = self.node_dict_factory
        self.node_attr_dict_factory = self.node_attr_dict_factory
        self.adjlist_outer_dict_factory = self.adjlist_outer_dict_factory
        self.adjlist_inner_dict_factory = self.adjlist_inner_dict_factory
        self.edge_attr_dict_factory = self.edge_attr_dict_factory

        self.graph = self.graph_attr_dict_factory()  # dictionary for graph attributes
        self._node = self.node_dict_factory()  # empty node attribute dict
        self._adj = self.adjlist_outer_dict_factory()  # empty adjacency dict
        # load graph attributes (must be after convert)
        self.graph.update(attr)

    def add_edge(self, u_of_edge, v_of_edge, **attr):
        
        u, v = u_of_edge, v_of_edge
        # add nodes
        if u not in self._node:
            self._adj[u] = self.adjlist_inner_dict_factory()
            self._node[u] = self.node_attr_dict_factory()
        if v not in self._node:
            self._adj[v] = self.adjlist_inner_dict_factory()
            self._node[v] = self.node_attr_dict_factory()
        # add the edge
        datadict = self._adj[u].get(v, self.edge_attr_dict_factory())
        datadict.update(attr)
        self._adj[u][v] = datadict
        self._adj[v][u] = datadict

    def is_multigraph(self):
        """Returns True if graph is a multigraph, False otherwise."""
        return False

    def is_directed(self):
        """Returns True if graph is directed, False otherwise."""
        return False

    def __iter__(self):
        """Iterate over the nodes. Use: 'for n in G'.
        Returns
        -------
        niter : iterator
            An iterator over all nodes in the graph.
        Examples
        --------
        >>> G = nx.path_graph(4)  # or DiGraph, MultiGraph, MultiDiGraph, etc
        >>> [n for n in G]
        [0, 1, 2, 3]
        >>> list(G)
        [0, 1, 2, 3]
        """
        return iter(self._node)



def is_inside(x, y, W, H, G):
    return (x <= H-1 and y <= W-1 and
            x >= 0 and y >= 0 and
            G[x][y] != "#")


def main():
    graph = Graph()
    H, W = map(int, input().split())
    Ch, Cw = map(int, input().split())
    Dh, Dw = map(int, input().split())
    G = [list(input()) for _ in range(H)]
    seen = set()

    for h in range(H):
        for w in range(W):
            v = h * W + w
            if not is_inside(h, w, W, H, G):
                continue
            for step_h in range(-2, 3):
                for step_w in range(-2, 3):
                    h_, w_ = h+step_h, w+step_w
                    v_ = h_ * W + w_
                    if is_inside(h_, w_, W, H, G) and v_ not in seen:
                        if ((max(abs(step_h), abs(step_w)) == 1) and
                                (min(abs(step_h), abs(step_w)) == 0)):
                            graph.add_edge(v, v_, weight=0)

                        else:
                            graph.add_edge(v, v_, weight=1)
            seen.add(v)
    
    start = (Ch - 1) * W + (Cw - 1)
    end = (Dh - 1) * W + (Dw - 1)
    try:
        ans = dijkstra_path_length(graph, start, end)
    except:
        ans = -1

    print(ans)


if __name__ == '__main__':
    main()


### FIXED CODE ###

from collections import deque


def is_inside(x, y, W, H, G):
    return (x <= H-1 and y <= W-1 and
            x >= 0 and y >= 0 and
            G[x][y] != "#")


def main():
    H, W = map(int, input().split())
    Cx, Cy = map(int, input().split())
    Dx, Dy = map(int, input().split())

    G = [list(input()) for _ in range(H)]
    INF = int(1e9)
    q = deque()
    q.append((Cx-1, Cy-1, -INF, Cx-1, Cy-1))
    warps = [[INF] * W for _ in range(H)]
    while q:
        x, y, warp, prev_x, prev_y = q.popleft()

        if warps[x][y] != INF:
            continue

        num_warps = warps[prev_x][prev_y] + warp
        warps[x][y] = num_warps

        for step_x in range(-2, 3):
            for step_y in range(-2, 3):
                x_, y_ = x+step_x, y+step_y
                if is_inside(x_, y_, W, H, G) and warps[x_][y_] == INF:
                    if ((max(abs(step_x), abs(step_y)) == 1) and
                            (min(abs(step_x), abs(step_y)) == 0)):

                        q.appendleft((x_, y_, 0, x, y))
                    else:
                        q.append((x_, y_, 1, x, y))

    ans = warps[Dx-1][Dy-1]
    if ans == INF:
        print(-1)
    else:
        print(ans)


if __name__ == '__main__':
    main()