#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define _overload3(_1,_2,_3,name,...) name
#define _rep(i,n) repi(i,0,n)
#define repi(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload3(__VA_ARGS__,repi,_rep,)(__VA_ARGS__)
#define VIEW(x) do {cerr << #x << ": "; for(auto i : x) cerr << i << " "; cerr << endl;} while(0)
#define ALL(x) (x).begin(),(x).end()
template<class T>bool umax(T &a, const T &b) {if(a<b){a=b;return 1;}return 0;}
template<class T>bool umin(T &a, const T &b) {if(b<a){a=b;return 1;}return 0;}

template<typename A,size_t N,typename T> void FILL(A (&array)[N],const T &val){fill((T*)array,(T*)(array+N),val);}
template<typename T> void FILL(vector<T> &v, const T &x) {fill(v.begin(), v.end(), x);}
template<typename T> void FILL(vector<vector<T>> &v, const T &x) {for(auto &i:v)fill(i.begin(), i.end(), x);}

const ll INF=1LL<<30;

struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) { }
  bool unite(int x, int y) {
    x = root(x); y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y]; data[y] = x;
    }
    return x != y;
  }
  bool find(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
};

pair<int,int> direction[] = {make_pair(0,-1), make_pair(-1,0), make_pair(1,0), make_pair(0,1)};
pair<int,int> direction5[] = {
  make_pair(1,-2),
  make_pair(-1,2),
  make_pair(1,2),
  make_pair(-1,-2),
  make_pair(2,-1),
  make_pair(-2,1),
  make_pair(2,1),
  make_pair(-2,-1),
  make_pair(2,-2),
  make_pair(-2,2),
  make_pair(2,2),
  make_pair(-2,-2),
  make_pair(1,-1),
  make_pair(-1,1),
  make_pair(1,1),
  make_pair(-1,-1),
  make_pair(0,-2),
  make_pair(-2,0),
  make_pair(2,0),
  make_pair(0,2),
  make_pair(0,-1),
  make_pair(-1,0),
  make_pair(1,0),
  make_pair(0,1)
};

int h,w, ch,cw,dh,dw;

int num(int i,int j) {
  return j + i*w;
}


int main() {
  cin >> h >> w;
  cin >> ch >> cw; ch--, cw--;
  cin >> dh >> dw; dh--, dw--;

  vector<string> grid(h);
  rep(i,h) cin >> grid[i];

  UnionFind uf(h*w);
  rep(i,h) rep(j,w) if(i>=0 && i<h && j>=0 && j<w && grid[i][j]=='.') {
    for(auto [hd,wd] : direction) {
      int ii = i+hd;
      int jj = j+wd;
      if(!(ii>=0 && ii<h && jj>=0 && jj<w)) continue;
      if(grid[ii][jj]=='#') continue;
      uf.unite(num(i,j), num(ii,jj));
    }
  }

  vector<int> vertices;
  map<int,int> num2index;
  rep(i,h) rep(j,w) if(i>=0 && i<h && j>=0 && j<w && grid[i][j]=='.') {
    int v = uf.root(num(i,j));
    if(num2index.count(v)) continue;
    num2index[v] = vertices.size();
    vertices.push_back(v);
  }

  int n=vertices.size();
//cerr << n << endl;
  vector<vector<int>> adj(n);

  rep(i,h) rep(j,w) if(i>=0 && i<h && j>=0 && j<w && grid[i][j]=='.') {
    for(auto [hd,wd] : direction5) {
      int ii = i+hd;
      int jj = j+wd;
      if(!(ii>=0 && ii<h && jj>=0 && jj<w)) continue;
      if(grid[ii][jj]=='#') continue;
      int from = num2index[uf.root(num(i,j))];
      int to = num2index[uf.root(num(ii,jj))];
      adj[from].push_back(to);
      adj[to].push_back(from);
    }
  }

  vector<int> dist(n, -1);
  int start = num2index[uf.root(num(ch,cw))];
  int goal  = num2index[uf.root(num(dh,dw))];
  dist[start] = 0;

  queue<int> q;
  q.push(start);

  while(q.size()) {
    int v = q.front(); q.pop();
    for(auto u : adj[v]) {
      if(dist[u]!=-1) continue;
      dist[u] = dist[v] + 1;
      q.push(u);
    }
  }
  cout << dist[goal] << endl;

}


Measured memory_bytes: 79744