//#pragma GCC optimize "trapv"
//-D_GLIBCXX_DEBUG
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
#define pm(m) for(auto itr=(m).begin();itr!=(m).end();itr++){itr->first<<" "<<itr->second<<"\n";}
#define int long long int
#define all(x) x.begin(),x.end()
#define allr(x) x.rbegin(),x.rend()
#define ii pair<int,int>
#define Max 100000+5
#define IO ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define f first
#define s second
#define pb push_back
#define bug(x) cout<<(x)<<" ";exit(0);
int mod = 1000000007;
int mod1 = 998244353;
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;



int power(int a,int b){
    if(b==1)return a;
    if(a>mod)a%=mod;
    int r=1;
    while(b){
        if(b&1)r=r%mod*a%mod;
        a=a%mod*a%mod;
        b/=2;
    }
    return r;
}
class uf{
    vector<int> v;
    vector<int> sz;
    
    
    public :
    uf(int n){
        v.resize(n+1);
        iota(v.begin()+1,v.end(),1);
        sz.resize(n+1,1);
        //1 to sz
    }
    int root(int b){
        while(v[b]!=b){
            b = v[b];
        }   
        return b;
    }
    void join(int a, int b){
        //combine a and 
        
        int ra=root(a);
        int rb=root(b);
        if(ra==rb)return ;
        if(sz[ra]<sz[rb])swap(ra,rb);
        v[rb]=ra;
        sz[ra]+=sz[rb];
        
    }
    bool same(int a,int b){
        //same set
        return (root(a)==root(b));
    }
    int size(int a){
        return sz[root(a)];
    }
   
    
};
vector<int> matmul(vector<int> a,vector<int> b){
    vector<int> c(4,0);
    c[0] = (a[0]%mod*b[0]%mod + a[1]%mod*b[2]%mod)%mod;
    c[1] = (a[0]%mod*b[1]%mod + a[1]%mod*b[3]%mod)%mod;
    c[2] = (a[2]%mod*b[0]%mod + a[3]%mod*b[2]%mod)%mod;
    c[3] = (a[2]%mod*b[1]%mod + a[3]%mod*b[3]%mod)%mod;
    return c;
}
vector<int> id={1,0,0,1};
vector<int> g[1000000];
vector<int> dis(1000000,-1);
int32_t main(){
	IO
	//freopen("input.txt","r",stdin);
    	//freopen("output.txt","w",stdout);
	
		
		int n,m;
		cin>>n>>m;
		int dx[]={1,0,-1,0};
		int dy[] = {0,1,0,-1};
		int cx,cy,rx,ry;
		cin>>cx>>cy>>rx>>ry;
		cx--;rx--;
		cy--;ry--;
		vector<vector<char> >  v(n,vector<char> (m));
	
		for(int i=0;i<n;i++){
		    for(int j=0;j<m;j++)cin>>v[i][j];
		}
		
		
		if(v[cx][cy]=='#' or v[rx][ry]=='#'){
		    cout<<"-1";
		    exit(0);
		}
		
		uf tree(n*m);
		
		vector<vector<bool> > vis(n,vector<bool> (m,0));
		
		
		for(int i=0;i<n;i++){
		    for(int j=0;j<m;j++){
		        if(v[i][j]=='.' and vis[i][j]==0){
		            //run a bfs
		            queue<ii> q;
		            q.push({i,j});
		            vis[i][j]=1;
		            
		            while(!q.empty()){
		                ii fr = q.front();
		                q.pop();
		                int x = fr.f;
		                int y = fr.s;
		                for(int k=0;k<4;k++){
		                    int nx = x+dx[k];
		                    int ny = y+dy[k];
		                    if(nx>=0 and nx<n and ny>=0 and ny<m and !vis[nx][ny] and v[nx][ny]=='.'){
		                        q.push({nx,ny});
		                        vis[nx][ny]=1;
		                        tree.join(i*m+j,nx*m+ny);
		                        
		                    }
		                }
		            }
		            
		            
		        }
		    }
		}
        
		if(tree.root(cx*m+cy)==tree.root(rx*m+ry)){
		    cout<<0;
		    exit(0);
		}
// 		for(int i=0;i<n;i++){
// 		    for(int j=0;j<m;j++){
// 		        if(v[i][j]=='.')
// 		        cout<<tree.root(i*m+j)<<" ";
// 		        else cout<<"-1 ";
// 		    }
// 		    cout<<endl;
// 		}
// 		exit(0);
		
		int dxx[]={-2,-1,0,1,2};
		map<ii,bool> edge;
		for(int i=0;i<n;i++){
		    for(int j=0;j<m;j++){
		        if(v[i][j]=='.'){
		            
		            int rb = tree.root(i*m+j);
		            
		            //run window 5x5
		            for(int k=0;k<5;k++){
		                for(int l=0;l<5;l++){
		                    int nx = i+dxx[k];
		                    int ny = j+dxx[l];
		                    
		                    if(nx>=0 and nx<n and ny>=0 and ny<m and v[nx][ny]=='.'){
		                      //  cout<<"Valid "<<nx<<" "<<ny<<"\n";
		                        int ra = tree.root(nx*m+ny);
    		                    if(tree.root(ra)!=tree.root(rb)){
    		                    
    		                        if(edge.find({ra,rb})==edge.end() and edge.find({rb,ra})==edge.end()){
    		                            
    		                            edge[{ra,rb}]=1;
    		                            g[ra].pb(rb);
    		                            g[rb].pb(ra);
    		                        }
    		                    }
		                    }
		                    
		                    
		                }
		            }
		            
		            
		            
		        }
		    }
		    
		}
		
		int ans=0;
	    //final bfs
	    int rooti = tree.root(cx*m+cy);
	    int rootf = tree.root(rx*m+ry);
	   
	    queue<int> q;
	    q.push(rooti);
	    dis[rooti]=0;
	    while(!q.empty()){
	        int u  = q.front();
	        q.pop();
	        for(auto v:g[u]){
	            if(dis[v]==-1){
	                dis[v]=dis[u]+1;
	                q.push(v);
	            }
	        }
	    }
	    cout<<dis[rootf];
	   // for(auto x:edge){
	   //     cout<<(x.f.f)<<" "<<(x.f.s)<<"\n";
	   // }
	
}

Measured memory_bytes: 69452