#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
#define all(x) x.begin(),x.end()
#define STRINGIFY(n) #n
#define TOSTRING(n) STRINGIFY(n)
#define PREFIX "#" TOSTRING(__LINE__) "| "
#define debug(x) \
{ \
  std::cout << PREFIX << #x << " = " << x << std::endl; \
}

std::ostream& output_indent(std::ostream& os, int ind) {
  for(int i = 0; i < ind; i++) os << " ";
  return os;
}

template<class S, class T> std::ostream& operator<<(std::ostream& os, const std::pair<S, T>& p);
template<class T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v);

template<class S, class T> std::ostream& operator<<(std::ostream& os, const std::pair<S, T>& p) {
  return (os << "(" << p.first << ", " << p.second << ")");
}
template<class T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
  os << "[";
  for(int i = 0;i < v.size();i++) os << v[i] << ", ";
  return (os << "]");
}

#include <set>
#include <vector>
using i64 = long long;

template<class F>
struct lattice_delta {
  i64 H, W;
  F f;
  using P = std::pair<i64, i64>;
  lattice_delta(i64 H, i64 W, F f): H(H), W(W), f(f) {}
  template<class Func>
  void operator()(P v, Func func) {
    const static std::vector<i64> dx { 1, 0, -1, 0 };
    i64 i = v.first;
    i64 j = v.second;
    for(i64 q = 0; q < 4; q++) {
      i64 x = i + dx[q];
      i64 y = j + dx[q ^ 1];
      if(0 <= x && x < H && 0 <= y && y < W) {
        f(P(i, j), P(x, y), func);
      }
    }
  }
};
 
template<class F>
lattice_delta<F> make_lattice_delta(i64 H, i64 W, F f) { return lattice_delta<F>(H, W, f); }
 
struct lattice_index {
  i64 H, W;
  using P = std::pair<i64, i64>;
  lattice_index(i64 H, i64 W): H(H), W(W) {}
  i64 operator()(P v) {
    return v.first * W + v.second;
  }
};

#include <vector>
#include <queue>
using i64 = long long;

/*
 * delta(V v, fn (V t, i64 weight))
 * index(V v) -> int
 */
template<class V, class W, class Delta, class Index>
std::vector<i64> dial01(std::size_t N, W inf, V s, Delta delta, Index index) {
  std::vector<i64> dist(N, inf);
  using P = std::pair<V, W>;
  std::deque<P> que;
  dist[index(s)] = 0;
  que.push_back({ s, dist[index(s)]});
  while(!que.empty()) {
    V v = que.front().first;
    W d = que.front().second;
    que.pop_front();
    if(dist[index(v)] < d) continue;
    delta(v, [&](V t, i64 weight) {
        if(dist[index(t)] > dist[index(v)] + weight) {
          dist[index(t)] = dist[index(v)] + weight;
          if(weight == 0) que.push_front({ t, dist[index(t)] });
          else que.push_back({ t, dist[index(t)] });
        }
    });
  }
  return dist;
}

int main() {
  i64 H, W;
  cin >> H >> W;
  i64 sx, sy;
  cin >> sx >> sy;
  sx--;
  sy--;
  i64 tx, ty;
  cin >> tx >> ty;
  tx--;
  ty--;
  vector<string> field(H);
  rep(i,0,H) {
    cin >> field[i];
  }
  lattice_index idx(H, W);
  auto lattice_func = 
      [&](auto p, auto q, auto func) {
        if(field[q.first][q.second] == '.') {
          func(q, 0);
        }
      };
  using P = pair<i64, i64>;
  auto ld = make_lattice_delta(H, W,lattice_func);
  auto delta = [&](auto p, auto func) {
    ld(p, func);
    rep(i,p.first - 2, p.first + 3) {
      rep(j,p.second - 2, p.second + 3) {
        if(0 <= i && i < H && 0 <= j && j < W && field[i][j] == '.') {
          func(P(i, j), 1);
        }
      }
    }
  };
  auto res = dial01(H * W, H * W + 10, P(sx, sy), delta, idx);
  auto ans = res[idx({tx, ty})];
  if(ans == H * W + 10) ans = -1;
  cout << ans << endl;
}


Measured memory_bytes: 13196