#include<cstdio>
#include<set>
#include<queue>
#include<deque>
#include<utility>
#include<cstring>
using namespace std;
using P = std::pair<int, int>;
int H, W, Ch, Cw, Dh, Dw;
unsigned block = 0;
const static int MAX_H = 1000, MAX_W = 1000;
bool is_road[MAX_H][MAX_W];
//int belong_block[MAX_H][MAX_W];
//bool has_been_visited[MAX_H][MAX_W];
int x[4] = {-1, 0, 1, 0};
int y[4] = {0, -1, 0, 1};
int d[MAX_H][MAX_W];
//int d[MAX_H*MAX_W>>1];
//std::set<unsigned> adj[MAX_H*MAX_W>>1];
//std::set<P> road;

bool is_inside_the_maze(int x, int y){
	return x >= 0 && x < H && y >= 0 && y < W;
}
/*
void Bfs(P start) {
    int start_x = start.first, start_y = start.second;
	std::queue<P> next_vertex_to_visit;
	next_vertex_to_visit.push(std::make_pair(start_x, start_y));
	has_been_visited[start_x][start_y] = true;
    belong_block[start_x][start_y] = block;

	while( !next_vertex_to_visit.empty() ) {
		P u = next_vertex_to_visit.front();
		next_vertex_to_visit.pop();
        road.erase(u);
		for (int i = 0; i < 4; ++i){
			int next_x = u.first + x[i], next_y = u.second + y[i];
			if(is_inside_the_maze(next_x, next_y) && is_road[next_x][next_y] && !has_been_visited[next_x][next_y]){
				has_been_visited[next_x][next_y] = true;
                belong_block[next_x][next_y] = block;
				next_vertex_to_visit.push(std::make_pair(next_x, next_y));
			}
		}
	}
}

void Bfs2(P start) {
    int start_x = start.first, start_y = start.second;
	std::queue<pair<P, unsigned>> next_vertex_to_visit;
	next_vertex_to_visit.push(std::make_pair(start, 5));
	has_been_visited[start_x][start_y] = true;
	while( !next_vertex_to_visit.empty() ) {
		P u = next_vertex_to_visit.front().first;
        unsigned type = next_vertex_to_visit.front().second;
		next_vertex_to_visit.pop();
        if(type == 0 || type == 2){
            int shift = x[type]*2;
            for (int i = -2; i < 3; i++){
                if(is_inside_the_maze(u.first + shift, u.second + i) && is_road[u.first + shift][u.second + i] && belong_block[u.first][u.second] != belong_block[u.first + shift][u.second + i]){
                    adj[belong_block[u.first + shift][u.second + i]].insert(belong_block[u.first][u.second]);
                    adj[belong_block[u.first][u.second]].insert(belong_block[u.first + shift][u.second + i]);
                }
            }
        }else if(type == 1 || type == 3){
            int shift = y[type]*2;
            for (int i = -2; i < 3; i++){
                if(is_inside_the_maze(u.first + i, u.second + shift) && is_road[u.first + i][u.second + shift] && belong_block[u.first][u.second] != belong_block[u.first + i][u.second + shift]){
                    adj[belong_block[u.first + i][u.second + shift]].insert(belong_block[u.first][u.second]);
                    adj[belong_block[u.first][u.second]].insert(belong_block[u.first + i][u.second + shift]);
                }
            }
        }else{
            for (int i = -2; i < 3; i++){
                for (int j = -2; j < 3; j++){
                    if(is_inside_the_maze(u.first + i, u.second + j) && is_road[u.first + i][u.second + j] && belong_block[u.first][u.second] != belong_block[u.first + i][u.second + j]){
                        adj[belong_block[u.first + i][u.second + j]].insert(belong_block[u.first][u.second]);
                        adj[belong_block[u.first][u.second]].insert(belong_block[u.first + i][u.second + j]);
                    }
                }
            }
        }
		for (unsigned i = 0; i < 4; ++i){
			int next_x = u.first + x[i], next_y = u.second + y[i];
			if(is_inside_the_maze(next_x, next_y) && is_road[next_x][next_y] && !has_been_visited[next_x][next_y]){
				has_been_visited[next_x][next_y] = true;
				next_vertex_to_visit.push(std::make_pair(std::make_pair(next_x, next_y), i));
			}
		}
	}
}

void Bfs3(unsigned s){
	queue<unsigned> q;
	q.push(s);
	for (unsigned i = 0; i < block; ++i) d[i] = -1;
	d[s] = 0;
	unsigned u;
	while(!q.empty()){
		u = q.front(); q.pop();
		for (auto i : adj[u]){
			if(d[i] == -1){
				d[i] = d[u] + 1;
				q.push(i);
			}
		}
	}
}
*/
void Bfs4(P start) {
    int start_x = start.first, start_y = start.second;
	std::deque<pair<P, pair<unsigned, unsigned> > > next_vertex_to_visit;
	next_vertex_to_visit.push_front(std::make_pair(start, std::make_pair(0, 5)));
	//has_been_visited[start_x][start_y] = true;
	while( !next_vertex_to_visit.empty() ) {
		P u = next_vertex_to_visit.front().first;
        unsigned type = next_vertex_to_visit.front().second.second, d_tmp = next_vertex_to_visit.front().second.first;
		next_vertex_to_visit.pop_front();
        if(d[u.first][u.second] >= 0) continue;
        d[u.first][u.second] = d_tmp;
        if(u.first == Dh && u.second == Dw) return;
		for (unsigned i = 0; i < 4; ++i){
			int next_x = u.first + x[i], next_y = u.second + y[i];
			if(is_inside_the_maze(next_x, next_y) && is_road[next_x][next_y] && d[next_x][next_y] < 0){
				next_vertex_to_visit.push_front(std::make_pair(std::make_pair(next_x, next_y), std::make_pair(d_tmp, i)));
			}
		}
        if(type == 0 || type == 2){
            int shift = x[type]*2;
            for (int i = -2; i < 3; i++){
                if(is_inside_the_maze(u.first + shift, u.second + i) && is_road[u.first + shift][u.second + i] && d[u.first + shift][u.second + i] < 0){
                    next_vertex_to_visit.push_back(std::make_pair(std::make_pair(u.first + shift, u.second + i), std::make_pair(d_tmp + 1, 5)));
                }
            }
        }else if(type == 1 || type == 3){
            int shift = y[type]*2;
            for (int i = -2; i < 3; i++){
                if(is_inside_the_maze(u.first + i, u.second + shift) && is_road[u.first + i][u.second + shift] && d[u.first + i][u.second + shift] < 0){
                    next_vertex_to_visit.push_back(std::make_pair(std::make_pair(u.first + i, u.second + shift), std::make_pair(d_tmp + 1, 5)));
                }
            }
        }else{
            for (int i = -2; i < 3; i++){
                for (int j = -2; j < 3; j++){
                    if(is_inside_the_maze(u.first + i, u.second + j) && is_road[u.first + i][u.second + j] && d[u.first + i][u.second + j] < 0){
                        next_vertex_to_visit.push_back(std::make_pair(std::make_pair(u.first + i, u.second + j), std::make_pair(d_tmp + 1, 5)));
                    }
                }
            }
        }
	}
}

int main(){
    scanf("%d %d\n%d %d\n%d %d", &H, &W, &Ch, &Cw, &Dh, &Dw);
    Ch--;Cw--;Dh--;Dw--;
    char tmp;
    for (int i = 0; i < H; i++){
        scanf("\n");
        for (int j = 0; j < W; j++){
            scanf("%c", &tmp);
            is_road[i][j] = tmp == '.';
            //if(is_road[i][j]) road.emplace(i, j);
        }
    }
    memset(d, -1, sizeof d);
    Bfs4(make_pair(Ch, Cw));
    printf("%d\n", d[Dh][Dw]);
    /*
    for (int i = 0; i < H; ++i) {
		for (int j = 0; j < W; ++j){
			has_been_visited[i][j] = false;
		}
	}
    vector<P> representative;
    while(!road.empty()){
        representative.push_back(*road.begin());
        Bfs(*road.begin());
        block++;
    }
    for (int i = 0; i < H; ++i) {
		for (int j = 0; j < W; ++j){
			has_been_visited[i][j] = false;
		}
	}
    for(auto i : representative){
        Bfs2(i);
    }
    Bfs3(belong_block[Ch][Cw]);
    printf("%d\n", d[belong_block[Dh][Dw]]);
    */
	return 0;
}

Measured memory_bytes: 8360