#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;i++)
#define repr(i,n) for(int i=n-1;i>=0;i--)
#define MAX(a,b) a=a>b?a:b
#define MIN(a,b) a=a<b?a:b
#define REP(i,x,n) for(int i=x;i<n;i++)
#define REPR(i,x,n) for(int i=n-1;i>=x;i--)
#define pb  push_back
#define ALL(obj) (obj).begin(), (obj).end()
#define ALLr(obj) (obj).rbegin(), (obj).rend()
#define endl "\n"
#define F first
#define S second
#define EN cout<<endl;
#define FAST ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;
typedef tuple<ll,ll,ll> PP;
typedef tuple<ll,ll,ll,ll> PPP;
typedef vector<ll> VLL;
typedef vector<VLL> VVLL;
typedef vector<P> VP;
typedef priority_queue<ll> PQ;
const ll mod=1000000007;
template<class T> void out(T a){cout<<a<<'\n';}
template<class T> void outp(T a){cout<<'('<<a.fi<<','<<a.se<<')'<<'\n';}
template<class T> void outvp(T v){rep(i,v.size())cout<<'('<<v[i].fi<<','<<v[i].se<<')';cout<<'\n';}
template<class T> void outvvp(T v){rep(i,v.size())outvp(v[i]);}
template<class T> void outv(T v){rep(i,v.size()){if(i)cout<<' ';cout<<v[i];}cout<<'\n';}
template<class T> void outvv(T v){rep(i,v.size())outv(v[i]);}
template<class T> bool isin(T x,T l,T r){return (l)<=(x)&&(x)<=(r);}
template<class T> void yes(T b){if(b)out("yes");else out("no");}
template<class T> void Yes(T b){if(b)out("Yes");else out("No");}
template<class T> void YES(T b){if(b)out("YES");else out("NO");}
template<class T> void no(T b){if(b)out("no");else out("yes");}
template<class T> void No(T b){if(b)out("No");else out("Yes");}
template<class T> void NO(T b){if(b)out("NO");else out("YES");}
template<class T> int sint(T s){int n;sscanf(s.c_str(),"%d",&n);return n;}
//combsort
template<typename T> void cSort(vector<T>& v){size_t h = (v.size()*10)/13;bool is_sorted = false;while(!is_sorted){if(h==1)is_sorted = true;for(size_t i=0; i<v.size()-h; ++i){if(v[i]>v[i+h]){swap(v[i],v[i+h]);if(is_sorted)is_sorted = false;}}if(h>1) h = (h*10)/13;if(h==0) h = 1;}}
ll gcd(ll a,ll b){if(b==0)return a;return gcd(b,a%b);}
ll modpow(ll a,ll b){ll res=1;a%=mod;while(b){if(b&1)res=res*a%mod;a=a*a%mod;b>>=1;}return res;}
template <int MOD>
struct ModInt {int val;ModInt(ll v = 0) : val(v % MOD) {if (val < 0) val += MOD;};ModInt operator+() const { return ModInt(val); }ModInt operator-() const { return ModInt(MOD - val); }ModInt inv() const { return this->pow(MOD - 2); }ModInt operator+(const ModInt& x) const { return ModInt(*this) += x; }ModInt operator-(const ModInt& x) const { return ModInt(*this) -= x; }ModInt operator*(const ModInt& x) const { return ModInt(*this) *= x; }ModInt operator/(const ModInt& x) const { return ModInt(*this) /= x; }ModInt pow(ll n) const {auto x = ModInt(1);auto b = *this;while (n > 0) {if (n & 1) x *= b;n >>= 1;b *= b;}return x;}ModInt& operator+=(const ModInt& x) {if ((val += x.val) >= MOD) val -= MOD;return *this;}ModInt& operator-=(const ModInt& x) {if ((val -= x.val) < 0) val += MOD;return *this;}ModInt& operator*=(const ModInt& x) {val = ll(val) * x.val % MOD;return *this;}ModInt& operator/=(const ModInt& x) { return *this *= x.inv(); }bool operator==(const ModInt& b) const { return val == b.val; }bool operator!=(const ModInt& b) const { return val != b.val; }friend istream& operator>>(istream& is, ModInt& x) noexcept { return is >> x.val; }friend ostream& operator<<(ostream& os, const ModInt& x) noexcept { return os << x.val; }};
constexpr int MOD = 998244353;
using mint = ModInt<MOD>;
class UnionFindTree
{
    vector<int> parent;
    vector<int> depth;
    vector<int> cnt;

public:
    UnionFindTree(int n) : parent(n), depth(n), cnt(n)
    {
        for (int i = 0; i < n; i++)
        {
            parent[i] = i;
            depth[i] = 0;
            cnt[i] = 1;
        }
    }

    //木の根を求める
    int find(int x)
    {
        if (parent[x] == x)
        {
            return x;
        }
        else
        {
            return parent[x] = find(parent[x]);
        }
    }

    //xとyの属する集合を併合
    void unite(int x, int y)
    {
        x = find(x);
        y = find(y);
        if (x == y)
            return;
        if (depth[x] < depth[y])
        {
            parent[x] = y;
            cnt[y] += cnt[x];
        }
        else
        {
            parent[y] = x;
            cnt[x] += cnt[y];
            if (depth[x] == depth[y])
                depth[x]++;
        }
    }
    // 同じ集合に属しているか判定
    bool same(int x, int y)
    {
        return find(x) == find(y);
    }
    // 集合のサイズを取得
    int size(int x)
    {
        return cnt[find(x)];
    }
};




//bool f[1000100]={};
int z[1000100]={};
VLL vx[1000100];

bool fff[1000100]={};
void cal(ll xz,ll cn){
    rep(i,vx[xz].size()){
        if(z[vx[xz][i]]>cn){
            z[vx[xz][i]]=cn;
            cal(vx[xz][i],cn+1);
        }
    }
}


int main(){
    FAST;
    ll n,h,w;cin>>h>>w;
    ll ans=0,c=0;
    UnionFindTree utree(h*w+10);
    vector<string>mp;
    ll num[1010][1010],cnt=0;
    ll ch,cw,dh,dw;
    cin>>ch>>cw>>dh>>dw;
    ch--;cw--;dh--;dw--;
    ll st,g;
    //st=ch*w+cw;g=dh*w+dw;
    rep(i,h){
        
        string s;cin>>s;
        mp.pb(s);
        rep(j,w){
            num[i][j]=cnt;
            if(i==ch&&j==cw)st=cnt;
            if(i==dh&&j==dw)g=cnt;
            z[cnt]=mod;
            cnt++;
        }
    }
    
    
    
    
    rep(i,h){
        rep(j,w){
            if(mp[i][j]=='.'){
                if(i+1<h)if(mp[i+1][j]=='.'){
                    utree.unite(num[i][j],num[i+1][j]);
                }
                if(j+1<w)if(mp[i][j+1]=='.'){
                    utree.unite(num[i][j],num[i][j+1]);
                }
            }
        }

    }

    if(utree.same(st,g)){
        out(0);
        return 0;
    }
    z[st]=0;
    VLL v;

    // rep(i,h){
    //     rep(j,w){
    //         if(z[num[i][j]]!=mod)
    //         cout<<z[num[i][j]]<<",";
    //         else cout<<"#,";
    //     }
    //     out("");
    // }


    
    rep(i,h){
        rep(j,w){
            if(mp[i][j]=='.'){
                REP(k,-2,3){
                    if(i+k<0||i+k>=h)continue;
                    REP(l,-2,3){
                        if(j+l<0||j+l>=w)continue;
                        if(mp[i+k][j+l]=='.'){
                            if(!utree.same(num[i][j],num[i+k][j+l])){
                                bool ff=1;
                                    ll un=utree.find(num[i][j]);
                                    ll un2=utree.find(num[i+k][j+l]);
                                    
                                    rep(q,vx[un].size()){
                                        if(vx[un][q]==un2){
                                            ff=0;
                                        }
                                    }
                                    if(ff==1){
                                        vx[un].pb(un2);
                                        vx[un2].pb(un);
                                    }
                            }
                        }
                    }
                }
            }
            
        }
        
    }
    z[utree.find(st)]=0;
    fff[utree.find(st)]=1;
    VLL vv;
    vv.pb(utree.find(st));
    ll cc=0,cnn=0,now=1;
    rep(i,vv.size()){
        
        rep(j,vx[vv[i]].size()){
            //if(i==0)out(vx[vv[i]][j]);
            if(fff[vx[vv[i]][j]]==1)continue;
            vv.pb(vx[vv[i]][j]);
            cnn++;
            fff[vx[vv[i]][j]]=1;
            z[vx[vv[i]][j]]=now;
        }
        //out(cnn);
        if(i==cc){
            cc+=cnn;
            cnn=0;
            now++;
        }
    }
    // rep(i,vx[vv[0]].size()){
    //     out(vx[vv[0]][i]);
    // }
    //cal(utree.find(st),1);
    // ll nn=0;
    // vector<pair<ll,P>>  vv;
    // vv.pb(pair<ll,P>(utree.find(st),P(ch,cw)));
    // rep(y,vv.size()){
    //     rep(i,h){
    //         rep
    //     }

    // }
    
// out("");
//     rep(i,h){
//         rep(j,w){
//             if(mp[i][j]=='.')cout<<utree.find(num[i][j]);
//             else cout<<("#");
//         }out("");
//     }
    if(z[utree.find(g)]==mod)out(-1);
    else out(z[utree.find(g)]);
    

}

/*
4 4
1 1
4 4
.#.#
#.#.
.#.#
#.#.
*/


Measured memory_bytes: 59352