#include<cstdio>
#include<set>
#include<queue>
#include<functional>
#include<utility>
#include<algorithm>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const static int MOD = 1000000007;
const static int MAX_N = 100000;
static const int INFTY = (1 << 21);
using P = std::pair<int, int>;
int H, W;
unsigned block = 0;
const static int MAX_H = 1000, MAX_W = 1000;//記入しよう
bool is_road[MAX_H][MAX_W];//trueなら道、falseなら壁
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>>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 block) {
    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;
    //belong_block[start_x][start_y] = block;

	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();
        //road.erase(u);
        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;
                //belong_block[next_x][next_y] = block;
				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);
			}
		}
	}
}
int main(){
    int Ch, Cw, Dh, Dw;
    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);
        }
    }
    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);
        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);
    }
    /*
    for (int i = 0; i < H; i++){
        for (int j = 0; j < W; j++){
            if(is_road[i][j]){
                for (int x = -2; x < 3; x++){
                    for (int y = -2; y < 3; y++){
                        if(is_inside_the_maze(i + x, j + y) && is_road[i+x][j+y] && belong_block[i][j] != belong_block[i+x][j+y]){
                            adj[belong_block[i+x][j+y]].insert(belong_block[i][j]);
                            adj[belong_block[i][j]].insert(belong_block[i+x][j+y]);
                        }
                    }
                }
            }
        }
    }
    */
    Bfs3(belong_block[Ch][Cw]);
    printf("%d\n", d[belong_block[Dh][Dw]]);
	return 0;
}

Measured memory_bytes: 56156