// C++(GCC 9.2.1)
#include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
using vvi = vector<vi>;
using P = pair<int, int>;
#define repex(i, a, b, c) for(int i = a; i < b; i += c)
#define repx(i, a, b) repex(i, a, b, 1)
#define rep(i, n) repx(i, 0, n)
#define repr(i, a, b) for(int i = a; i >= b; i--)
#define a first
#define b second
#define pb push_back
// constexpr int MAX = 1010;
constexpr int MAX = 1010101;
constexpr int dx[] = {-1, 0, 1, 0}, dy[] = {0, -1, 0, 1};
int board[MAX];      // 迷路情報.
int connection[MAX]; // 連結成分番号を保存.
int d[MAX];          // 開始頂点 からの 距離 を 保存.

// https://ja.wikipedia.org/wiki/幅優先探索
// 迷路を幅優先探索する.
// ※bfsの動作確認用.
// @param s: 探索開始地点の迷路上の座標.
// @param H: 行数.
// @param W: 列数.
// @param l: 連結成分番号(※1以上).
// @return: 特に無し.
void bfs(int s, int H, int W, int l){
    
    // 1. 空のキュー.
    queue<int> q;
    
    // 2. 訪問済みフラグ設定.
    connection[s] = l;
    
    // 3. 探索地点 s をキュー q に追加.
    q.push(s);
    while(!q.empty()){
        // 4. キューから取り出す.
        int v = q.front();
        q.pop();
        // 5. 取り出した要素を処理.
        // x: 列方向, y: 行方向 で考える.
        int nx, ny, n;
        int cx = v % W , cy = v / W;
        rep(i, 4){
            nx = cx + dx[i];
            ny = cy + dy[i];
            n = nx + ny * W;
            // printf("cx=%d nx=%d cy=%d ny=%d\n", cx, nx, cy, ny);
            
            // 6. 訪問不可能なマス であれば, 処理をスキップ.
            if(nx < 0 || nx >= W || ny < 0 || ny >= H) continue;
            if(board[n])                               continue;
            
            // 7. 訪問先のマスで, 訪問可能 かつ 未訪問 であれば, 連結成分を設定.
            if(!board[n] && !connection[n]) connection[n] = l, q.push(n);
        }
    }
    return;
}

// https://ja.wikipedia.org/wiki/幅優先探索
// ※bfsの動作確認用.
// @param G: グラフ.
// @param s: グラフの探索開始頂点.
// @param d: 探索開始地点からの距離.
// @return: 特に無し.
void bfs(vvi &G, int s, int* d){
    // 1. 空のキュー.
    queue<int> q;
    
    // 2. 訪問済みフラグ設定.
    d[s] = 0;    // スタート地点は, 距離ゼロを指定.
    
    // 3. 探索地点 s をキュー q に追加.
    q.push(s);
    while(!q.empty()){
        // 4. キューから取り出す.
        int u = q.front();
        q.pop();
        
        // 5. 取り出した要素を処理.
        for(auto &e : G[u]){
            // 6. 訪問済であれば, 処理をスキップ.
            if(d[e])            continue;
            if(!d[e] && e != s) d[e] = d[u] + 1, q.push(e);
        }
    }
    return;
}

int main() {
    
    // 1. 入力情報取得.
    int H, W, sh, sw, gh, gw;
    scanf("%d %d %d %d %d %d", &H, &W, &sh, &sw, &gh, &gw);
    sh--, sw--, gh--, gw--;
    rep(i, H){
        char c[1010];
        scanf("%s", c);
        int l = strlen(c);
        rep(j, W) if(c[j] == '#') board[i * W + j] = 1;
    }
    // rep(i, H){
    //     rep(j, W) printf("%d", board[i * W + j]);
    //     puts("");
    // }
    
    // 2. 探索を行い, 連結成分に分割.
    int idx = 0;
    rep(i, H){
        rep(j, W){
            int cur = i * W + j;
            if(!connection[cur] && !board[cur]) bfs(cur, H, W, ++idx);
        }
    }
    // rep(i, H){
    //     rep(j, W) printf("%d", connection[i * W + j]);
    //     puts("");
    // }
    
    // 3. 開始地点, ゴール地点の連結成分番号.
    int cs = connection[sh * W + sw];
    int cg = connection[gh * W + gw];
    
    // 4. ワープを使って移動できるか判定.
    set<P> s;
    rep(i, H){
        rep(j, W){
            int cur = i * W + j; // 現在位置.
            if(!board[cur]){
                int u = max(i - 2, 0);     // 最上行.
                int d = min(i + 2, H - 1); // 最下行.
                int l = max(j - 2, 0);     // 最左列.
                int r = min(j + 2, W - 1); // 最右列.
                repx(h, u, d + 1){
                    repx(w, l, r + 1){
                        int nex = h * W + w;
                        if(cur != nex && !board[nex]){
                            int cc = connection[cur];   // 現在位置の連結成分番号.
                            int cn = connection[nex];   // 移動先の連結成分番号.
                            if(cc == cn) continue;      // 同じだったら次へ.
                            if(cc > cn) swap(cc, cn);   // 大小入れ替え.
                            s.insert({cc - 1, cn - 1}); // グラフの頂点情報を登録.
                        }
                    }
                }
            }
        }
    }
    // for(auto &p : s) printf("%d %d\n", p.a, p.b);
    
    // 5. グラフ作成.
    vvi G(idx);
    for(auto &p : s){
        G[p.a].pb(p.b);
        G[p.b].pb(p.a);
    }
    
    // 6. 開始地点 から 各頂点 までの距離を計算.
    bfs(G, cs - 1, d);
    // rep(i, H){
    //     rep(j, W) printf("%d", d[i * W + j]);
    //     puts("");
    // }
    
    // 7. 出力.
    int ans = -1;
    if(cs == cg) ans = 0;
    if(cs != cg && d[cg - 1]) ans = d[cg - 1];
    printf("%d\n", ans);
    return 0;
    
}

Measured memory_bytes: 28100