#include <bits/stdc++.h>
using namespace std;
template<class T> ostream& operator<<(ostream &os, vector<T> V) { os << "[ "; 
  for(auto v:V)os << v << " "; return os << "]";
}
template<class T> ostream& operator<<(ostream &os, set<T> S){ os << "{ "; 
  for(auto s:S) os<<s<<" ";  return os<<"}"; 
}
template<class L, class R> ostream& operator<<(ostream &os, pair<L,R> P) {
  return os<<"("<<P.first<<","<< P.second << ")";
}
template<class L, class R> ostream& operator<<(ostream &os, map<L,R> M) {
  os<<"{ ";for(auto m:M)os<<"("<<m.first<<":"<<m.second<<")";
  return os<<"}";
}
#define cerr cout
#define TRACE
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...) 1
#endif
// #include <ext/pb_ds/assoc_container.hpp> 
// #include <ext/pb_ds/tree_policy.hpp> 
// using namespace __gnu_pbds;
// #define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
// find_by_order(k)  returns iterator to kth element starting from 0;
// order_of_key(k) returns count of elements strictly smaller than k;
//For multiset use less_equal operator but it does support erase operations for multiset
#define ll long long
#define ld long double
#define vll vector<ll>
#define pll pair<ll,ll>
#define vpll vector<pll>
#define I insert 
#define pb push_back
#define F first
#define S second
#define endl "\n"
#define all(v) (v).begin(),(v).end()
#define For(i,n) for(int i=0;i<(int)n;++i)
#define Rev(i,n) for(int i=(int)n-1;i>=0;--i)
#define Rep(i,n) for(int i=1;i<=(int)n;++i)
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<pii,int> ppi;
typedef vector<pii> vpi;
#define fio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define mp make_pair
// inline void modadd(int &a,int &b){a+=b;if(a>=mod)a-=mod;} 
const int N = 1e3 + 100;
const int mod = 1e9;
char grid[N][N];
int comp[N][N];
int h , w;
int dx[] = {-1 , 0 , 1, 0};
int dy[] = {0 , 1 ,  0 , -1};
bool inside(int x, int y){
  if(x >= 0 && x < h && y >= 0 && y < w) return true;
  else return false;
}

void dfs(int i, int j, int curr){
  comp[i][j] = curr; 
  for(int k =0;k < 4 ; ++k){
    int x = i+dx[k]; 
    int y = j+dy[k];
    if(!inside(x,y)) continue;
    if(grid[x][y] == '#') continue;
    if(comp[x][y] == 0){
      dfs(x, y , curr);
    }
  }
}
int dis[N*N];
int vis[N*N];
vi G[N*N];



int main(){
  fio; cout<<fixed<<setprecision(25);	
  cin >> h >> w;
  int ch,cw,dh,dw;
  cin >> ch >> cw >> dh >> dw;
  for(int i = 0;i < h ; ++i){
    for(int j =0;j < w ; ++j) cin >> grid[i][j];
  }
  int curr = 0;
  for(int i = 0;i < h ; ++i){
    for(int j = 0;j < w ; ++j){
      if(comp[i][j] == 0) 
        dfs(i , j , ++curr);
    }
  }

  for(int i = 0;i < h ; ++i){
    for(int j = 0;j < w ; ++j){
      dis[w*i+j] = mod;
      for(int k = -2 ; k <= 2; ++k){
        for(int l = -2 ; l <= 2 ; ++l){
          int x = i+k;
          int y = j+l;
          if(!inside(x,y)) continue;
          if(grid[i][j] == '#' || grid[x][y] == '#') continue;
          if(comp[x][y] != comp[i][j]){
            //cout << i << "," << j << " : " << x << ',' << y << endl;
            //cout << comp[i][j] << ' ' << comp[x][y] << endl;
            G[comp[x][y]].pb(comp[i][j]);
            G[comp[i][j]].pb(comp[x][y]);
          }
        }
      }
    }
  }

  int c = comp[ch-1][cw-1];
  dis[c] = 0;
  queue<int> Q;
  Q.push(c);
  while(Q.size()){
    auto u = Q.front();
    Q.pop();
    for(auto it : G[u]){
      if(dis[it] > dis[u]+1){
        dis[it] = dis[u]+1;
        Q.push(it);
      }
    }
  }
  if(dis[comp[dh-1][dw-1]] == mod){
    cout << -1 << endl;
  }
  else{
    cout << dis[comp[dh-1][dw-1]] << endl;
  }



  

}


Measured memory_bytes: 63168