#include <bits/stdc++.h>
using namespace std;
template<class C>constexpr int sz(const C&c){return int(c.size());}
using ll=long long;constexpr const char nl='\n',sp=' ';

struct ZeroOneBFS {
  using Edge = tuple<int, int, int>; vector<int> dist, par;
  template <class WeightedGraph>
  ZeroOneBFS(const WeightedGraph &G, const vector<int> &srcs)
      : dist(G.size(), INT_MAX), par(G.size(), -1) {
    vector<int> q(G.size()), stk(G.size()); int front = 0, back = 0, top = 0;
    for (int s : srcs) dist[stk[top++] = s] = 0;
    while (top > 0 || front < back) {
      int v = top > 0 ? stk[--top] : q[front++]; for (auto &&e : G[v]) {
        int w = e.first; if (dist[w] > dist[v] + e.second) {
          (e.second == 0 ? stk[top++] : q[back++]) = w;
          dist[w] = dist[par[w] = v] + e.second;
        }
      }
    }
  }
  template <class WeightedGraph> ZeroOneBFS(const WeightedGraph &G, int s)
      : ZeroOneBFS(G, vector<int>{s}) {}
  vector<Edge> getPath(int v) {
    vector<Edge> path; for (; par[v] != -1; v = par[v])
      path.emplace_back(par[v], v, dist[v] - dist[par[v]]);
    reverse(path.begin(), path.end()); return path;
  }
};

template <class T> struct StaticWeightedGraph {
  vector<int> ST, TO, A, B; vector<T> C, WEIGHT;
  StaticWeightedGraph(int V) : ST(V + 1, 0) {}
  void reserveDiEdges(int maxEdges) {
    TO.reserve(maxEdges); A.reserve(maxEdges); B.reserve(maxEdges);
  }
  void addDiEdge(int from, int to, T weight) {
    ST[from]++; A.push_back(from); B.push_back(to); C.push_back(weight);
  }
  void addBiEdge(int v, int w, T weight) {
    addDiEdge(v, w, weight); addDiEdge(w, v, weight);
  }
  void build() {
    partial_sum(ST.begin(), ST.end(), ST.begin()); TO = B; WEIGHT = C;
    for (int e = 0; e < int(A.size()); e++) {
      TO[--ST[A[e]]] = B[e]; WEIGHT[ST[A[e]]] = C[e];
    }
  }
  struct Iterator {
    const StaticWeightedGraph &G; int i;
    Iterator(const StaticWeightedGraph &G, int i) : G(G), i(i) {}
    Iterator &operator ++ () { i++; return *this; }
    pair<int, T> operator * () const {
      return make_pair(G.TO[i], G.WEIGHT[i]);
    }
    bool operator != (const Iterator &it) const { return i != it.i; }
  };
  struct Adj {
    const StaticWeightedGraph &G; int v;
    Adj(const StaticWeightedGraph &G, int v) : G(G), v(v) {}
    const Iterator begin() const { return Iterator(G, G.ST[v]); }
    const Iterator end() const { return Iterator(G, G.ST[v + 1]); }
  };
  const Adj operator [] (int v) const { return Adj(*this, v); }
  int size() const { return int(ST.size()) - 1; }
};

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // freopen("err.txt", "w", stderr);
  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  int H, W, CH, CW, DH, DW;
  cin >> H >> W >> CH >> CW >> DH >> DW;
  --CH; --CW;
  --DH; --DW;
  StaticWeightedGraph<int> G(H * W);
  vector<string> S(H);
  auto to1d = [&] (int i, int j) {
    return i * W + j;
  };
  for (int i = 0; i < H; i++) cin >> S[i];
  for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) if (S[i][j] == '.') {
    for (int di = -2; di <= 2; di++) for (int dj = -2; dj <= 2; dj++) {
      if (di == 0 && dj == 0) continue;
      int ii = i + di, jj = j + dj;
      if (0 <= ii && ii < H && 0 <= jj && jj < W && S[ii][jj] == '.') {
        G.addDiEdge(to1d(i, j), to1d(ii, jj), abs(di) + abs(dj) == 1 ? 0 : 1);
      }
    }
  }
  G.build();
  int ans = ZeroOneBFS(G, to1d(CH, CW)).dist[to1d(DH, DW)];
  cout << (ans == INT_MAX ? -1 : ans) << nl;
  return 0;
}


Measured memory_bytes: 140472