#include<iostream>
#include<algorithm>
#include<vector>
#include<numeric>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<deque>
#include<bitset>
#include<iomanip>
#include<cctype>
#include<map>
#include<cstring>
#include<bitset>
#include<cassert>

#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rep2(i,a,b) for (int (i)=a;(i)<(b);(i)++)
#define all(x) (x).begin(),(x).end()

using namespace std;
using ll = long long int;

const int inf = 1001001000;
const long long int Inf = 1001001001001001000;



void print(vector<vector<int>> a){
	for (int i = 0; i < a.size(); i++)
	{
		for (int j=0;j<a[i].size();j++){
			cout << a[i][j] << " ";
		}
		cout << endl;
	}
}

void print(vector<vector<long long int>> a){
	for (int i=0;i<a.size();i++){
		for (int j=0;j<a[i].size();j++){
			cout << a[i][j] << " ";
		}
		cout << endl;
	}
}

void print(vector<int> a){
    int n = a.size();
    for (int j=0;j<n;j++) {
        if (j != n-1) cout << a[j] << " ";
        else cout << a[j] << endl;
    }
}

void print(vector<long long int> a){
    int n = a.size();
    for (int j=0;j<n;j++) {
        if (j != n-1) cout << a[j] << " ";
        else cout << a[j] << endl;
    }
}

void print(set<int> a){
	for (auto x:a)
		cout << x << " ";
	cout << endl;
}

//幅優先探索のテンプレ.デフォルトではstartからの距離を返す.
//graphは隣接リスト.startは探索開始地点
vector<int> bfs(vector<vector<int>> &graph, int start){
	queue<int> todo;
	vector<int> dist(graph.size(),-1);
	dist[start] = 0;
	todo.push(start);
	while(!todo.empty()){
		int now = todo.front();
		todo.pop();
		for (int i=0;i<graph[now].size();i++){
			int nxt = graph[now][i];
			if (dist[nxt] != -1) continue;
			dist[nxt] = dist[now] + 1;
			todo.push(nxt);
		}
	}
	return dist;
}

//ダイクストラ法のテンプレ.
//graphはコスト付きの隣接リスト(node,costの順にpairに格納).
//startからの最短距離が格納されたvectorを返す.
// int v,e,r; cin >> v >> e >> r; /*v:#頂点数,b:#辺の数,r:開始地点*/
// vector<vector<pair<int,int>>> graph(v,vector<pair<int,int>>());
// for (int i = 0; i < e;i++){
// 	int a,b,c; cin >> a >> b >> c; /*a:from,b:to,c:cost*/
// 	graph[a].push_back(pair<int,int>(b,c));
// }
vector<int> dijkstra(vector<vector<pair<int,int>>> graph, int start){
	int inf = 2001001000;
	priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> que;
	vector<int> dist(graph.size(),inf);
	dist[start] = 0;
	que.push(pair<int,int>(0,start));
	while(!que.empty()){
		pair<int,int> now = que.top();
		que.pop();
		int c = now.first, from = now.second;
		if (dist[from] < c) continue;
		for (int i = 0; i < graph[from].size(); i++){
			int to = graph[from][i].first, cost = graph[from][i].second;
			if (dist[to] > dist[from] + cost){
				dist[to] = dist[from] + cost;
				que.push(pair<int,int>(dist[to],to));
			}
		}
	}
	return dist;
}

int main()
{
	int h, w;
	cin >> h >> w;
	int ch, cw, dh, dw;
	cin >> ch >> cw >> dh >> dw;
	ch++;
	cw++;
	dh++;
	dw++;

	vector<string> m(h + 4, string(w + 4, '#'));
	rep(i,h){
		string s;
		cin >> s;
		rep(j,w){
			m[i + 2][j + 2] = s[j];
		}
	}
	// rep(i,m.size()){
	// 	cout << m[i] << endl;
	// }
	h += 4;
	w += 4;
	vector<vector<pair<int,int>>> graph((h+0)*(w+0),vector<pair<int,int>>());
	rep(i, m.size()){
		rep(j,m[i].size()){
			vector<int> temp;
			int id = i * w + j;
			if (m[i][j] == '.')
			{
				rep2(k,-2,3){
					rep2(l,-2,3){
						if(m[i+k][j+l] == '.'){
							graph[id].push_back(pair<int, int>(w*(i+k) + (j + l), 1));
						}
					}
				}
				// int id = w * i + j;
				if (m[i-1][j] == '.'){
					graph[id].push_back(pair<int, int>(w*(i-1) + (j + 0), 0));
				}
				if (m[i+1][j] == '.'){
					graph[id].push_back(pair<int, int>(w*(i+1) + (j + 0), 0));
				}
				if (m[i][j-1] == '.'){
					graph[id].push_back(pair<int, int>(w*(i-0) + (j -1), 0));
				}
				if (m[i][j+1] == '.'){
					graph[id].push_back(pair<int, int>(w*(i+0) + (j +1), 0));
				}
			}
		}
	}

	vector<int> dist = dijkstra(graph, ch * w + cw);
	// print(dist);
	int ans = dist[dh * w + dw];
	if (ans == 2001001000)
		ans = -1;
	cout << ans << endl;

	return 0;
}

Measured memory_bytes: 208824