#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <math.h>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <functional>
#include <queue>
#include <unordered_set>
#include <climits>
#include <set>
#include <list>
#include <cmath>
#include <map>

using namespace std;
typedef long long ll;

struct Edge;
struct Node{
	ll cost;
	bool isClosed;
	vector<Edge*> edges;
	Node* last;
	
	Node(){}
};

struct NODE{
	Node* node;
	ll costWhenPushed;
	bool operator<(const NODE& rhs) const { return costWhenPushed > rhs.costWhenPushed; } // 逆にする
	NODE(Node* n, ll cost){
		node = n;
		costWhenPushed = cost;
	}
};

struct Edge{
	Node* node0;
	Node* node1;
	ll cost;
};

vector<Node> Nodes;
vector<Edge> Edges;

ll Dijkstra_Find(Node* s, Node* g){
	// 初期化
	for(int i = 0; i < Nodes.size(); i++){
		Nodes[i].cost = &Nodes[i] == s ? 0 : LLONG_MAX / 2;
		Nodes[i].isClosed = false;
		Nodes[i].last = nullptr;
	}
	priority_queue<NODE> que;
	que.push(NODE(s, 0));
	
	while(!que.empty()){
		Node* n = que.top().node;
		ll costWhenPushed = que.top().costWhenPushed;
		que.pop();
		if(n->cost < costWhenPushed){
			continue;
		}
		n->isClosed = true;
		
		int size = (n->edges).size();
		for(int i = 0; i < size; i++){
		  Node* processNode = (n->edges)[i]->node0 == n ? (n->edges)[i]->node1 : (n->edges)[i]->node0;
			if(processNode->isClosed){
				continue;
			}
			
			ll newCost = n->cost + (n->edges)[i]->cost;
			if( newCost < processNode->cost ){
				processNode->cost = newCost;
				processNode->last = n;
				que.push(NODE(processNode, newCost));
			}
		}
	}
	
	return g->cost;
}

int main()
{
	int wall = 99999999;
	int H, W;
	int Ch, Cw, Dh, Dw;
	cin >> H >> W >> Ch >> Cw >> Dh >> Dw;
	static int Mass[1002][1002];
	for(int i = 0; i < 1002; i++){
		for(int j = 0; j < 1002; j++){
			Mass[i][j] = wall;
		}
	}
	int count = 0;
	for(int h = 1; h <= H; h++){
		string line;
		cin >> line;
		for(int w = 1; w <= W; w++){
			if(line[w-1] == '.'){
				count++;
				Mass[h][w] = count;
			}
		}
	}
	
	for(int step = 0; step < 50; step++){
		for(int h = 1; h <= H; h++){
			for(int w = 1; w <= W; w++){
				if(Mass[h][w] != wall){
					Mass[h][w] = min(Mass[h][w], Mass[h-1][w]);
					Mass[h][w] = min(Mass[h][w], Mass[h][w-1]);
					Mass[h][w] = min(Mass[h][w], Mass[h+1][w]);
					Mass[h][w] = min(Mass[h][w], Mass[h][w+1]);
				}
			}
		}
	}
	
	static int Mass2[1010][1010];
	for(int i = 0; i < 1010; i++){
		for(int j = 0; j < 1010; j++){
			Mass2[i][j] = wall;
		}
	}
	set<int> counter;
	map<int, int> cor;
	for(int h = 1; h <= H; h++){
		for(int w = 1; w <= W; w++){
			if(Mass[h][w] != wall){
				if(counter.find(Mass[h][w]) == counter.end()){
						counter.insert(Mass[h][w]);
						cor[Mass[h][w]] = counter.size();
				}
				Mass2[h][w] = cor[Mass[h][w]];
			}else{
				Mass2[h][w] = wall;
			}
		}
	}
	
	/*
	for(int h = 1; h <= H; h++){
		for(int w = 1; w <= W; w++){
			cout << Mass2[h][w] << " ";
		}
		cout << endl;
	}
	*/
	
	for(int i = 0; i < counter.size()+2; i++){
		Node node;
		Nodes.push_back(node);
	}
	for(int i = 0; i < 1000*1000; i++){
		Edge edge;
		Edges.push_back(edge);
	}
	
	int edgeCount = 0;
	set<pair<int, int> > check;
	for(int h = 1; h <= H; h++){
		for(int w = 1; w <= W; w++){
			if(Mass2[h][w] == wall){
				continue;
			}
			Node* node1 = &Nodes[Mass2[h][w]];
			for(int x = -2; x <= 2; x++){
				for(int y = -2; y<=2; y++){
					if(x != 0 || y != 0){
						if(h+x >= 0 && h+x <= H && w+y >= 0 && w+y <= W){
							//cout << h << " " << w << " "<< h+x << " " << w+y << endl;
							//cout << Mass2[h][w] << endl;
							if(Mass2[h+x][w+y] == wall){
								// pass
							}
							else if(Mass2[h][w] != Mass2[h+x][w+y]){
								if(check.find(make_pair(min(Mass2[h][w], Mass2[h+x][w+y]), max(Mass2[h][w], Mass2[h+x][w+y]))) != check.end() ){
									continue;
								}
								Node* node2 = &Nodes[Mass2[h+x][w+y]];
								Edge* edge12 = &Edges[edgeCount];
								edge12->node0 = node1;
								edge12->node1 = node2;
								edge12->cost = 1;
								node1->edges.push_back(edge12);
								node2->edges.push_back(edge12);
								edgeCount++;
								check.insert(make_pair(min(Mass2[h][w], Mass2[h+x][w+y]), max(Mass2[h][w], Mass2[h+x][w+y])));
							}
						}
					}
				}
			}
		}
	}
	
	ll ans = Dijkstra_Find(&Nodes[Mass2[Ch][Cw]], &Nodes[Mass2[Dh][Dw]]);
	if(ans > 100010001000){
		ans = -1;
	}
	cout << ans << endl;
	
	return 0;
}


Measured memory_bytes: 71092