#include <bits/stdc++.h>
using namespace std;
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}
#ifdef __LOCAL
#define debug(x) cerr << __LINE__ << ": " << #x << " = " << x << endl
#define debugArray(x, n)                             \
  cerr << __LINE__ << ": " << #x << " = {";          \
  for (long long hoge = 0; (hoge) < (n); ++(hoge)) { \
    cerr << ((hoge) ? "," : "") << x[hoge];          \
  }                                                  \
  cerr << "}" << endl
#else
#define debug(x) (void(0))
#define debugArray(x, n) (void(0))
#endif

struct UnionFind {
  vector<int> par;
  UnionFind(int size) : par(size, -1) {}
  bool unite(int u, int v) {
    if ((u = root(u)) == (v = root(v))) return false;
    if (par[u] > par[v]) swap(u, v);
    par[u] += par[v], par[v] = u;
    return true;
  }
  bool same(int u, int v) { return root(u) == root(v); }
  int root(int u) { return par[u] < 0 ? u : par[u] = root(par[u]); }
  int size(int u) { return -par[root(u)]; }
};

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int H, W;
  cin >> H >> W;
  int Ch, Cw;
  cin >> Ch >> Cw;
  Ch--, Cw--;
  int Dh, Dw;
  cin >> Dh >> Dw;
  Dh--, Dw--;
  vector<string> S(H);
  for (int i = 0; i < H; i++) cin >> S[i];
  UnionFind uf(H * W);
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      if (S[i][j] == '#') continue;
      int cur = i * W + j;
      if (i > 0 && S[i - 1][j] == '.') uf.unite(cur, (i - 1) * W + j);
      if (j > 0 && S[i][j - 1] == '.') uf.unite(cur, i * W + j - 1);
      if (i + 1 < H && S[i + 1][j] == '.') uf.unite(cur, (i + 1) * W + j);
      if (j + 1 < W && S[i][j + 1] == '.') uf.unite(cur, i * W + j + 1);
    }
  }
  int id[H * W];
  fill(id, id + H * W, -1);
  int cnt = 0;
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      if (S[i][j] == '#') continue;
      int cur = uf.root(i * W + j);
      if (id[cur] != -1) continue;
      id[cur] = cnt++;
    }
  }
  vector<vector<int>> graph(cnt);
  for (int i = 0; i < H; i++) {
    for (int j = 0; j < W; j++) {
      if (S[i][j] == '#') continue;
      int v = id[uf.root(i * W + j)];
      debug(v);
      for (int di = -2; di <= 2; di++) {
        for (int dj = -2; dj <= 2; dj++) {
          if (di == 0 && dj == 0) continue;
          int ni = i + di, nj = j + dj;
          if (ni < 0 || H <= ni || nj < 0 || W <= nj) continue;
          if (S[ni][nj] == '#') continue;
          int u = id[uf.root(ni * W + nj)];
          debug(ni);
          debug(nj);
          debug(u);
          if (u == v) continue;
          graph[v].push_back(u);
        }
      }
    }
  }
  for (int i = 0; i < cnt; i++) debug(graph[i].size());
  int dist[cnt];
  const int INF = INT_MAX / 10;
  fill(dist, dist + cnt, INF);
  int s = id[uf.root(Ch * W + Cw)];
  dist[s] = 0;
  queue<pair<int, int>> que;
  que.push(make_pair(s, 0));
  while (!que.empty()) {
    int v, d;
    tie(v, d) = que.front();
    que.pop();
    if (dist[v] < d) continue;
    for (int u : graph[v]) {
      if (dist[u] > dist[v] + 1) {
        dist[u] = dist[v] + 1;
        que.push(make_pair(u, dist[u]));
      }
    }
  }
  int ans = dist[id[uf.root(Dh * W + Dw)]];
  if (ans == INF) ans = -1;
  cout << ans << endl;
  return 0;
}


Measured memory_bytes: 25376