#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <map>

using namespace std;
#line 1 "graph/template.cpp"
#include <vector>

template< typename T >
struct Edge {
  int from, to;
  T cost;
  Edge() {}
  Edge(int f, int t) : from(f), to(t), cost(1) {}
  Edge(int f, int t, T c) : from(f), to(t), cost(c) {}
  friend bool operator < (const Edge& lhs, const Edge& rhs) { return lhs.cost < rhs.cost; };
  friend bool operator > (const Edge& lhs, const Edge& rhs) { return rhs < lhs; };
  friend bool operator <= (const Edge& lhs, const Edge& rhs) { return !(lhs > rhs); };
  friend bool operator >= (const Edge& lhs, const Edge& rhs) { return !(lhs < rhs); };
};

template< typename T >
using Edges = std::vector< Edge< T > >;
template< typename T >
using Graph = std::vector< Edges< T > >;
#line 2 "graph/dijkstra.cpp"

#include <algorithm>
#include <functional>
#include <limits>
#include <queue>
#include <utility>
#line 9 "graph/dijkstra.cpp"

template < typename T >
struct Dijkstra {
  using P = std::pair<T, int>; // <始点からの距離, 点のid>
  const T INF; // 十分に大きいがoverflowしない値として、型Tの最大値の半分を使う
  const int V; // 頂点数
  Graph<T> g;
  std::vector<T> dist; // 始点からの距離
  std::vector<bool> visit; // すでに探索済みの点か
  Dijkstra(Graph<T> &g): INF(std::numeric_limits<T>::max()/2), V(g.size()), g(g), dist(V), visit(V) {}
  Dijkstra(Graph<T> &g, int V): INF(std::numeric_limits<T>::max()/2), V(V), g(g), dist(V), visit(V) {}
  void init(int s) {
    std::fill(dist.begin(), dist.end(), INF);
    std::fill(visit.begin(), visit.end(), false);
    dist[s] = T(); // 始点の距離を0で初期化
    std::priority_queue<P, std::vector<P>, std::greater<P>> pq;
    pq.push({dist[s], s});
    while (!pq.empty()) {
      P node = pq.top(); pq.pop();
      int from = node.second;
      if (visit[from]) continue;
      visit[from] = true;
      for (auto &e : g[from]) {
        if (visit[e.to]) continue;
        T d = node.first + e.cost;
        if (d >= dist[e.to]) continue;
        dist[e.to] = d;
        pq.push({d, e.to});
      }
    }
  }
};


int H, W;
int id(int h, int w) {
  return h*W+w;
}

bool out(int h, int w, vector<string>& grid) {
  if (h < 0 || h >= H) return true;
  if (w < 0 || w >= W) return true;
  if (grid[h][w] == '#') return true;
  return false;
}

int DX[4] = {0, 1, 0, -1};
int DY[4] = {1, 0, -1, 0};

int main() {
  cin >> H >> W;
  int ch, cw; cin >> ch >> cw;
  --ch; --cw;
  int dh, dw; cin >> dh >> dw;
  --dh; --dw;
  vector<string> grid;
  Graph<int> g(H*W);
  for (int i = 0; i < H; ++i) {
    string s; cin >> s;
    grid.push_back(s);
  }
  for (int h = 0; h < H; ++h) {
    for (int w = 0; w < W; ++w) {
      if (out(h, w, grid)) continue;
      int i = id(h, w);
      for (int j = 0; j < 4; ++j) {
        int nh = h+DX[j];
        int nw = w+DY[j];
        if (out(nh, nw, grid)) continue;
        int ni = id(nh, nw);
        g[i].emplace_back(i, ni, 0);
      }
      for (int j = -2; j <= 2; ++j) {
        for (int k = -2; k <= 2; ++k) {
          if (abs(j)+abs(k) <= 1) continue;
          int nh = h+j;
          int nw = w+k;
          if (out(nh,nw,grid)) continue;
          int ni = id(nh, nw);
          g[i].emplace_back(i, ni, 1);
        }
      }
    }
  }
  Dijkstra<int> dj(g);
  dj.init(id(ch,cw));
  int ans = dj.dist[id(dh,dw)];
  if (ans == dj.INF) ans = -1;
  cout << ans << endl;
}



Measured memory_bytes: 232944