#include <bits/stdc++.h>

#define M_PI       3.14159265358979323846   // pi

using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
typedef tuple<ll, ll, ll> t3;

#define rep(a,n) for(ll a = 0;a < n;a++)

static const ll INF = 1e15;
static const ll mod = 1e9+7;

template<typename T>
static inline void chmin(T& ref, const T  value) {
    if (ref > value) ref = value;
}

template<typename T>
static inline void chmax(T& ref, const T value) {
    if (ref < value) ref = value;
}

struct UnionFind {
public:
    vector <ll> par; // 
    vector <ll> siz; // 

    UnionFind() {}

    UnionFind(ll sz_) : par(sz_), siz(sz_, 1LL) {
        for (ll i = 0; i < sz_; ++i) par[i] = i;
    }
    void init(ll sz_) {
        par.resize(sz_);
        siz.assign(sz_, 1LL);
        for (ll i = 0; i < sz_; ++i) par[i] = i;
    }

    ll root(ll x) {
        while (par[x] != x) {
            x = par[x] = par[par[x]];
        }
        return x;
    }

    bool merge(ll x, ll y) {
        x = root(x);
        y = root(y);
        if (x == y) return false;
        if (siz[x] < siz[y]) swap(x, y);
        siz[x] += siz[y];
        par[y] = x;
        return true;
    }

    bool issame(ll x, ll y) {
        return root(x) == root(y);
    }

    ll size(ll x) {
        return siz[root(x)];
    }
};

ll h, w;

ll id(ll i, ll j) {
    return i * w + j;
}

P toP(ll id) {
    return { id / w, id % w };
}


int main() {
    cin >> h >> w;
    P c, d;
    cin >> c.second >> c.first;
    c.second--; c.first--;
    cin >> d.second >> d.first;
    d.second--; d.first--;
    vector<vector<bool>> grid(h, vector<bool>(w, false));
    rep(i, h) {
        rep(j, w) {
            char a;
            cin >> a;
            grid[i][j] = a == '.';
        }
    }
    UnionFind uf(h* w);
    rep(i, h) {
        rep(j, w) {
            if (!grid[i][j]) continue;
            if (i > 0) {
                if (grid[i - 1][j]) {
                    uf.merge(id(i - 1, j), id(i, j));
                }
            }
            if (i < h-1) {
                if (grid[i + 1][j]) {
                    uf.merge(id(i, j), id(i+1, j));
                }
            }
            if (j > 0) {
                if (grid[i][j - 1]) {
                    uf.merge(id(i, j-1), id(i, j));
                }
            }
            if (j < w-1) {
                if (grid[i][j + 1]) {
                    uf.merge(id(i, j), id(i, j + 1));
                }
            }
        }
    }
    ll sId = -1;
    ll gId = -1;
    map<int, set<int>> graph;
    rep(i, h) {
        rep(j, w) {
            if (!grid[i][j]) continue;
            ll current = uf.root(id(i, j));
            if (i == c.second && j == c.first) {
                sId = current;
            }
            if (i == d.second && j == d.first) {
                gId = current;
            }
            for (int dy = -2; dy <= 2; dy++) {
                for (int dx = -2; dx <= 2; dx++) {
                    ll y = dy + i;
                    ll x = dx + j;
                    if (y >= 0 && y < h) {
                        if (x >= 0 && x < w) {
                            if (grid[y][x]) {
                                ll nid = uf.root(id(y, x));
                                if (nid == current) continue;
                                graph[current].insert(nid);
                                graph[nid].insert(current);
                            }
                        }
                    }
                }
            }
        }
    }
    if (sId == gId) {
        cout << 0 << endl;
        return 0;
    }
    priority_queue<P, vector<P>, greater<P>> qu;
    qu.emplace(0, sId);
    vector<ll> dist(h* w, INF);
    while (!qu.empty()) {
        auto t = qu.top(); qu.pop();
        if (dist[t.second] <= t.first) continue;
        dist[t.second] = t.first;
        for (auto& p : graph[t.second]) {
            auto ncost = t.first + 1;
            if (dist[p] <= ncost) continue;
            qu.emplace(ncost, p);
        }
    }
    if (dist[gId] == INF) {
        cout << -1 << endl;
    }
    else {
        cout << dist[gId] << endl;
    }
    return 0;
}


Measured memory_bytes: 57948