#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <iomanip>
#include <map>
#include <set>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <iterator>
#include <string>
#include <limits>

using namespace std;

using i64 = int64_t;
using P = pair<i64, i64>;
i64 mod = 1000000007;
//i64 mod = 998244353;
int int_max = 2147483647;
i64 INF = 1e16;
int max_n = 1e5;


template<typename IntType>
struct mat2d_t {
    mat2d_t(size_t h, size_t w) : h(h), w(w) {
        mat = std::vector<std::vector<IntType>>(h, std::vector<IntType>(w, 0));
    }
    mat2d_t(size_t h, size_t w, IntType init) : h(h), w(w){
        mat = std::vector<std::vector<IntType>>(h, std::vector<IntType>(w, init));
    }

    std::vector<IntType>& operator[](size_t p) {
        return mat[p];
    }

    const std::vector<IntType>& operator[](size_t p) const {
        return mat[p];
    }
    size_t height() const {
        return h;
    }
    size_t width() const {
        return w;
    }

private:
    std::vector<std::vector<IntType>> mat;
    size_t h;
    size_t w;
};

void dijkstra(std::vector<set<i64>>& g, std::vector<i64>& d, int s) {
    priority_queue<P, std::vector<P>, greater<P>> que;
    d[s] = 0;
    que.push(make_pair(0, s));
    while(!que.empty()) {
        P p = que.top(); que.pop();
        int v = p.second;
        if (d[v] < p.first) continue;
        for (i64 e : g[v]) {
            if (d[e] > d[v] + 1) {
                d[e] = d[v] + 1;
                que.push(make_pair(d[e], e));
            }
        }
    }
}


bool dfs(mat2d_t<i64>& m, i64 x, i64 y, i64 idx) {
    if (m[y][x] != 0) return false;
    m[y][x] = idx;
    size_t h = m.height();
    size_t w = m.width();

    if(0 < x && m[y][x-1]==0) dfs(m, x-1, y, idx);
    if(x+1 < w  && m[y][x+1]==0) dfs(m, x+1, y, idx);
    if(0 < y && m[y-1][x]==0) dfs(m, x, y-1, idx);
    if(y+1 < h && m[y+1][x]==0) dfs(m, x, y+1, idx);

    return true;
}

void scan_link(mat2d_t<i64>& m, i64 x, i64 y, vector<set<i64>>& graph) {
    std::set<i64> v;
    for (int i=x; i<x+3; ++i) {
        if (i>=m.width()) continue;
        for (int j=y; j<y+3; ++j) {
            if (j>=m.height()) continue;
            if (0 < m[j][i]) {
                v.insert(m[j][i]);
            }
        }
    }
    for (auto n:v) {
        for (auto n2:v) {
            if (n==n2) continue;
            graph[n].insert(n2);
        }
    }
}

int main(int argc, char **argv) {
    i64 h,w;
    cin >> h >> w;
    i64 sy,sx,ey,ex;
    cin >> sy >> sx >> ey >> ex;
    --sy; --sx; --ex; --ey;

    mat2d_t<i64> m(h, w, 0);
    for (int i=0; i<h; ++i) {
        for (int j=0; j<w; ++j) {
            char c;
            cin >> c;
            m[i][j] = (c=='#'? -1: 0);
        }
    }

    i64 idx{1};
    for (int i=0; i<h; ++i) {
        for (int j=0; j<w; ++j) {
            if (dfs(m, j, i, idx)) ++idx;
        }
    }
/*
    for (int i=0; i<h; ++i) {
        for (int j=0; j<w; ++j) {
            cout << m[i][j] << " ";
        }
        cout << endl;
    }
*/

    vector<set<i64>> graph(idx+1);
    for (int i=0; i<h; ++i) {
        for (int j=0; j<w; ++j) {
            scan_link(m, j, i, graph);
        }
    }
    i64 start = m[sy][sx];
    i64 end = m[ey][ex];
/*
    for (auto v: graph) {
        for (i64 num: v) {
            cout <<num<<" ";
        }
        cout << endl;
    }
*/
    vector<i64> distance(idx+1, int_max);
    dijkstra(graph, distance, start);

    cout << (distance[end] == int_max ? -1 : distance[end]) << endl;
    return 0;
}


Measured memory_bytes: 36092