#include <bits/stdc++.h>
using namespace std;
 
//////////////////

#ifdef DEBUG
    #include "debug.h"
    #define dump(...)                                                              \
        DUMPOUT << "  " << string(#__VA_ARGS__) << ": "                            \
                << "[" << to_string(__LINE__) << ":" << __FUNCTION__ << "]"        \
                << endl                                                            \
                << "    ",                                                         \
            dump_func(__VA_ARGS__)
#else
    #define dump(...)
#endif


// http://beet-aizu.hatenablog.com/entry/2018/04/08/145516
template<typename T>
vector<T> make_v(size_t a){return vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
  return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

template<typename T,typename V>
typename enable_if<is_class<T>::value==0>::type
fill_v(T &t,const V &v){t=v;}

template<typename T,typename V>
typename enable_if<is_class<T>::value!=0>::type
fill_v(T &t,const V &v){
  for(auto &e:t) fill_v(e,v);
}

//////////////////

#define int long long
 
#define rep(i,n) for(int i=0, i##_len=(n); i<i##_len; ++i)

#define YES puts("YES")
#define Yes puts("Yes")
#define NO  puts("NO")
#define No  puts("No")
#define ALL(v) (v).begin(), (v).end()
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }

//*
#define mod 1000000007 /*/
#define mod 998244353 //*/

typedef pair<int, int> P;
#define INF (1LL<<60)

const int dx[4] = { 1, 0, -1, 0 };
const int dy[4] = { 0, 1, 0, -1 };

struct Edge {
    int to;     // 辺の行き先
    int weight; // 辺の重み
    Edge(int t, int w) : to(t), weight(w) { }
};
using Graph = vector<vector<Edge>>;

void solve(){
    int H, W;
    cin >> H >> W;
    int ch, cw, dh, dw;
    cin >> ch >> cw >> dh >> dw;
    ch--; cw--; dh--; dw--;
    
    vector<string> S(H);
    rep(i,H) cin >> S[i];
    
    auto Z = [&](int a, int b){ return a*W + b;};
    
    Graph G;
    G.resize(H*W);
    
    rep(i,H)rep(j,W){
        if(S[i][j]=='#') continue;
        
        rep(k,4){
            int ni = i+dx[k];
            int nj = j+dy[k];
            if(0<=ni && ni<H && 0<=nj && nj<W){
                if(S[ni][nj]=='.'){
                    G[Z(i,j)].push_back({Z(ni,nj),0});
                    G[Z(ni,nj)].push_back({Z(i,j),0});// これだと二重に張られてる？
                }
            }
        }
        
        int ddx[] = {2,2,2, 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1,0,1};
        int ddy[] = {2,1,0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2,2,2};
        
        for(int x = -2; x<=2; x++)for(int y=-2; y<=2; y++){
        if(x==0 && y==0) continue;
//        rep(k,16){
        int ni = i+x;//ddx[k];
        int nj = j+y;//ddy[k];
            if(0<=ni && ni<H && 0<=nj && nj<W){
                if(S[ni][nj]=='.'){
                    G[Z(i,j)].push_back({Z(ni,nj),1});
                    G[Z(ni,nj)].push_back({Z(i,j),1});
                }
            }
        }
    }
    
    vector<int> dist(G.size(), INF);
    vector<bool> seen(G.size(), false);

    deque<int> q;
    int start = Z(ch,cw);
    int goal = Z(dh, dw);
    q.push_front(start);
    seen[start] = true;
    dist[start] = 0;

    while (!q.empty()) {
      int u = q.front(); q.pop_front();
        
      for (auto e : G[u]) {

          int d2 = min(dist[e.to], dist[u] + e.weight);
          if(dist[e.to] > d2){
                dist[e.to] = d2;
                if(e.weight==0){
                    q.push_front(e.to);
                }else{
                    q.push_back(e.to);
                }
            }
          }
    }
    dump(dist);
    if(dist[goal] == INF) dist[goal] = -1;
    cout << dist[goal] << endl;
}


signed main(){
    cout << fixed << setprecision(18);
//    cerr << fixed << setprecision(18);
    solve();
}


Measured memory_bytes: 340196