#include <bits/stdc++.h>
using namespace std;
/* typedef */
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
/* constant */
const int INF = 1 << 30;
const ll LINF = 1LL << 50;
const int NIL = -1;
const int MAX = 1004;
const int mod = 1000000007;
const double pi = 3.141592653589;
/* global variables */
vector<int> dxA = {0, 0, 1, -1};
vector<int> dyA = {1, -1, 0, 0};
vector<int> dxB = {-2,-2,-2,-2,-2,-1,-1,-1,-1,0,0,1,1,1,1,2,2,2,2,2};
vector<int> dyB = {-2,-1,0,1,2,-2,-1,1,2,-2,2,-2,-1,1,2,-2,-1,0,1,2};
vector<vector<int>> color, dist;
vector<vector<int>> maze(MAX, vector<int>(MAX));
vector<vector<vector<piii>>> G;
int h, w, sx, sy, gx, gy;
/* function */
void input() {
    cin >> h >> w >> sx >> sy >> gx >> gy;
    sx--, sy--, gx--, gy--;
    for (int i = 0; i < h; i++) for (int j = 0; j < w; j++) {
        char c; cin >> c;
        if (c == '#') maze[i][j] = 0;
        else maze[i][j] = 1;
    }
}
bool canMove(int x, int y) {
    if (x < 0 || h <= x || y < 0 || w <= y) return false;
    if (maze[x][y] == 0) return false;
    return true;
}
void bfsCol(int s, int t) {
    queue<pii> q;
    q.emplace(s, t);
    while (!q.empty()) {
        pii p = q.front();
        q.pop();
        int x = p.first, y = p.second;
        // moveA
        for (int i = 0; i < dxA.size(); i++) {
            int nx = x + dxA[i], ny = y + dyA[i];
            if (!canMove(nx, ny)) continue;
            if (color[nx][ny] == NIL) {
                color[nx][ny] = color[x][y];
                q.emplace(nx, ny);
            }
        }
    }
}
int bfsB() {
    dist.assign(MAX, vector<int>(MAX, INF));
    queue<pii> q;
    q.emplace(sx, sy);
    dist[sx][sy] = 0;
    while (!q.empty()) {
        pii p = q.front();
        q.pop();
        int x = p.first, y = p.second;
        // moveB
        for (int dx = -2; dx <= 2; dx++) { for (int dy = -2; dy <= 2; dy++) {
            if (dx == 0 && dy == 0) continue;
            int nx = x + dx, ny = y + dy;
            if (!canMove(nx, ny)) continue;
            if (color[x][y] == color[nx][ny]) {
                if (dist[nx][ny] > dist[x][y]) {
                    dist[nx][ny] = dist[x][y];
                    q.emplace(nx, ny);
                }
            }
            else {
                if (dist[nx][ny] > dist[x][y] + 1) {
                    dist[nx][ny] = dist[x][y] + 1;
                    q.emplace(nx, ny);
                }
            }
        }
        }
    }
    return dist[gx][gy];
}
int bfs01() {
    dist.assign(MAX, vector<int>(MAX, INF));
    list<pii> ls;
    ls.emplace_back(sx, sy);
    dist[sx][sy] = 0;
    while (ls.size()) {
        pii p = ls.front();
        ls.pop_front();
        int x = p.first, y = p.second;
        // ls = [x, x+1]
        // 距離が同じ -> push_front -> [x, x, x+1]
        // 距離増える -> push_back -> [x, x+1, x+1]
        // moveA
        for (int i = 0; i < dxA.size(); i++) {
            int nx = x + dxA[i], ny = y + dyA[i];
            if (!canMove(nx, ny)) continue;
            if (dist[nx][ny] > dist[x][y]) {
                dist[nx][ny] = dist[x][y];
                ls.emplace_front(nx, ny);
            }
        }
        // moveB
        for (int i = 0; i < dxB.size(); i++) {
            int nx = x + dxB[i], ny = y + dyB[i];
            if (!canMove(nx, ny)) continue;
            if (dist[nx][ny] > dist[x][y] + 1) {
                dist[nx][ny] = dist[x][y] + 1;
                ls.emplace_back(nx, ny);
            }
        }
    }
    return dist[gx][gy];
}
void drawColor() {
    color.assign(MAX, vector<int>(MAX, -1));
    int curColor = 0;
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            if (maze[i][j] == 1 && color[i][j] == -1) {
                color[i][j] = curColor++;
                bfsCol(i, j);
            }
        }
    }
}
void makeEdge() {
    // dxA, dyAで移動できるマス, コスト0の有向辺
    // dxB, dyBで移動できるマス, コスト1の有向辺
    G.assign(MAX, vector<vector<piii>>(MAX, vector<piii>()));
    for (int x = 0; x < h; x++) for (int y = 0; y < w; y++) {
        // moveA
        for (int i = 0; i < dxA.size(); i++) {
            int nx = x + dxA[i], ny = y + dyA[i];
            if (!canMove(nx, ny)) continue;
            G[x][y].push_back(piii(0, pii(nx, ny)));
        }
        // moveB
        for (int i = 0; i < dxB.size(); i++) {
            int nx = x + dxB[i], ny = y + dyB[i];
            if (!canMove(nx, ny)) continue;
            G[x][y].push_back(piii(1, pii(nx, ny)));
        }
    }
}
int dijkstra() {
    color.assign(MAX, vector<int>(MAX));
    dist.assign(MAX, vector<int>(MAX, INF));
    dist[sx][sy] = 0;
    priority_queue<piii> pq;
    pq.push(piii(0, pii(sx, sy)));
    while (!pq.empty()) {
        piii from = pq.top();
        pq.pop();
        int minD = (-1) * from.first;
        int x = from.second.first, y = from.second.second;
        if (minD > dist[x][y]) continue;
        color[x][y] = 1;
        for (piii to : G[x][y]) {
            int cost = to.first;
            int nx = to.second.first, ny = to.second.second;
            if (color[nx][ny]) continue;
            if (dist[nx][ny] > dist[x][y] + cost) {
                dist[nx][ny] = dist[x][y] + cost;
                pq.push(piii((-1) * dist[nx][ny], pii(nx, ny)));
            }
        }
    }
    return dist[gx][gy];
}
void printAns(int ans) {
    if (ans == INF) cout << -1 << '\n';
    else cout << ans << '\n';
}
void solve1() {
    // bfsで色分け
    // ex)
    // #0###
    // ####2
    // #11##
    // #11##
    drawColor();
    // bfsで最小回数探索
    printAns(bfsB());
}
void solve2() {
    // 01-bfs
    printAns(bfs01());
}
void solve3() {
    // dijkstra
    makeEdge();
    printAns(dijkstra());
}
/* main */
int main(){
    input();
    // solve1();
    // solve2();
    solve3();
}


Measured memory_bytes: 240660