#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 ll long long int
#define ld long double
#define ordered_set tree < ll ,  null_type ,  less<ll> ,  rb_tree_tag ,  tree_order_statistics_node_update >
//added two more functions to set
//(1)*(set.find_by_order(k))[kth element in the sorted set] 
//(2)set.order_of_key(k)[count of elements strictly less than k]

typedef vector< int > vi;
typedef vector<long long> lvi;
typedef vector< vector<int> > vvi;
typedef vector< vector<long long> > lvvi;
typedef pair< int,int > ii;
typedef pair< long long,long long > lii;
typedef vector<pair<int,int>> vii;
typedef vector<pair<long long,long long>> lvii;
typedef vector<vector<pair<int,int>>> vvii;
typedef vector<vector<pair<long long,long long>>> lvvii;
typedef vector<bool> vb;

// #ifdef ONLINE_JUDGE 
// #define endl '\n'
// #endif
#define pb push_back
#define all(c) (c).begin(),(c).end()
#define tr(c,i) for(auto i = (c).begin(); i != (c).end(); i++)//remember i is an iterator
#define tc(t) int (t); cin>>(t);while((t)--)
#define ff first
#define ss second
#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " is " << a << endl;
	err(++it, args...);
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
const long long mod = 1e9 + 7;
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

long long mos() { return 0LL; }
template<typename T, typename... Args>
T mos(T a, Args... args) { return ((a + mos(args...))%mod + mod)%mod; }

long long mop() { return 1LL; }
template<typename T, typename... Args>
T mop(T a, Args... args) { return (a*mop(args...))%mod; }
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

string s[1005];
ll sx,sy,dx,dy;
ll h,w;

ll d[1005][1005];
const int inf = 1e9;

int nx[]={-1,1,0,0};
int ny[]={0,0,-1,1};

void dks()
{
	for (int i = 0; i < 1005; ++i)
	{
		for (int j = 0; j < 1005; ++j)
		{
			d[i][j]=inf;
		}
	}
	d[sx][sy]=0;
	priority_queue<pair<int,ii>,vector<pair<int,ii>>,greater<pair<int,ii>>> pq;
	pq.push({0,{sx,sy}});
	while(!pq.empty())
	{
		auto curr = pq.top();
		pq.pop();
		auto [cx,cy]=curr.ss;
		if(d[cx][cy]!=curr.ff) continue;
		for(int i=0;i<4;i++)
		{
			int kx=cx+nx[i],ky=cy+ny[i];
			if(kx>=0&&kx<h && ky>=0 && ky<w && s[kx][ky]!='#')
			{
				if(d[kx][ky]>d[cx][cy])
				{
					d[kx][ky]=d[cx][cy];
					pq.push({d[kx][ky],{kx,ky}});
				}
			}
		}
		for(int i=-2;i<=2;i++)
		{
			for(int j=-2;j<=2;j++)
			{
				int kx=cx+i,ky=cy+j;
				if(kx>=0&&kx<h && ky>=0 && ky<w && s[kx][ky]!='#')
				{
					if(d[kx][ky]>d[cx][cy]+1)
					{
						d[kx][ky]=d[cx][cy]+1;
						pq.push({d[kx][ky],{kx,ky}});
					}		
				}
			}	
		}
	}
}


signed main()
{
	ios_base::sync_with_stdio(false);
    cin.tie(NULL);	
	cin>>h>>w;
	cin>>sx>>sy>>dx>>dy;
	sx--;sy--;dx--;dy--;
	for (int i = 0; i < h; ++i)
	{
		cin>>s[i];
	}
	dks();
	if(d[dx][dy]==inf) cout<<"-1"<<endl;
	else cout<<d[dx][dy]<<endl;
	return 0;
}	


// WA
// 1. overflow
// 2. re-initialize global variables for every test case.
// 3. edge cases like n=1

// Run time error
// 1. division by zero.
// 2. array bounds.

// TLE
// 1. uncomment that #define endl '\n' line

Measured memory_bytes: 12600