#include <bits/stdc++.h>

#define all(X) (X).begin(), (X).end()
#define rep(I, A, B) for (int I = (A); I < (B); ++I)
#define ll long long
#define ld long double
#define linf (1ll << 60)

using namespace std;

struct Edge {
    int node;
    ll dist;
    Edge(int _n, int _v) : node(_n), dist(_v){}
};

struct Graph {
    vector<vector<Edge>> adj; 
    int N;

    ll inf = LLONG_MAX;
    vector<ll> dist;
	vector<int> pv;

    Graph(int N) {
        this->N = N;
        dist.resize(N, inf);
        pv.resize(N, -1);
        adj.resize(N);
    }

    void initDist() {
        fill(all(dist), inf);
        fill(all(pv), -1);
    }

    void addEdge(int src, int des, int dist) {adj[src].emplace_back(Edge(des, dist));}

	// ----- Dijkstra ----- //
    void dijkstra(int src) {
        auto comp = [](Edge a, Edge b) { return a.dist > b.dist; };
        priority_queue<Edge, vector<Edge>, decltype(comp)> pq(comp);
        pq.emplace(Edge(src, 0));
		dist[src] = 0;
        while(!pq.empty()){
            Edge cur = pq.top();
            pq.pop();
            int u = cur.node;
            for (auto& next : adj[u]) {
                int v = next.node;
                int weight = next.dist;
                if (dist[u] + weight < dist[v]) {
                    dist[v] = dist[u] + weight;
                    pv[v] = u;
                    pq.emplace(Edge(v, dist[v]));
                }
            }
        }
        return;
    }

	vector<int> getShortestPath(int src, int dst) {
        vector<int> res;
		if (dist[src] != 0) {
			cout << "src dist isn't 0 !" << '\n';
			return res;
		}
		if (dist[dst] == inf) {
            res.emplace_back(-1);
            return res;
		}

		int t = dst;
		stack<int> path;
		path.push(dst);
		while (pv[t] != -1) {
			path.push(pv[t]);
			t = pv[t];
		}

		while(!path.empty()) {
            int _t = path.top();
            path.pop();
			res.emplace_back(_t);
		}

		return res;
	}
};


// -------- Main Code -------- //
vector<int> dir_row = {0, 1, 0, -1}; 
vector<int> dir_col = {1, 0, -1, 0};
int row, col, s_r, s_c, e_r, e_c;

int getIdx(int r, int c) {
    return r * col + c;
}
 
void runcase() {
    cin >> row >> col;
    cin >> s_r >> s_c >> e_r >> e_c;
    s_r --;
    s_c --;
    e_r --;
    e_c --;

    Graph g(row * col + 5);

    vector<vector<char>> arr(row, vector<char>(col, '\0'));

    string s;
    rep(i,0,row) {
        cin >> s;
        rep(j, 0, col) arr[i][j] = s[j];
    }

    // for (int i=0; i<row; i++) {
    //     for (int j=0; j<col; j++) {
    rep(i, 0, row) {
        rep(j, 0, col) {
            if (arr[i][j] == '#') continue;
            rep(k, 0, dir_row.size()) {
                int tr = i + dir_row[k];
                int tc = j + dir_col[k];
                if (tr < 0 || tc < 0 || tr >= row || tc >= col) continue;
                int idx_u = getIdx(i, j);
                int idx_v = getIdx(tr, tc);
                if (arr[tr][tc] == '.') {
                    g.addEdge(idx_u, idx_v, 0);
                    g.addEdge(idx_v, idx_u, 0);
                }
            }
            // for (int _i = -2; _i <= 2; _i ++) {
            //     for (int _j = -2; _j <= 2; _j ++) {
            rep (_i, -2, 3) rep (_j, -2, 3) {
                int tr = i + _i;
                int tc = j + _j;
                if (tr < 0 || tc < 0 || tr >= row || tc >= col) continue;
                if (arr[tr][tc] == '#') continue;
                int idx_u = getIdx(i, j);
                int idx_v = getIdx(tr, tc);
                g.addEdge(idx_u, idx_v, 1);
                g.addEdge(idx_v, idx_u, 1);
            }
        }
    }

    int src = getIdx(s_r, s_c);
    int dst = getIdx(e_r, e_c);
    g.initDist();
    g.dijkstra(src);
    ll res = g.dist[dst];

    if (res == LLONG_MAX) res = -1;

    cout << res << '\n';
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    // int t;
    // cin >> t;
    // while (t-- > 0)
        runcase();
    return 0;
}


Measured memory_bytes: 372152