#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define linf (1ll << 60)
#define all(x) (x).begin(), (x).end()

template <typename Key, typename Value, typename Arg>
bool containsKey(const map<Key, Value>& m, const Arg& value) {return m.find(value) != m.end();}

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(dist.begin(), dist.end(), inf);
        fill(pv.begin(), pv.end(), -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;
    for (int i=0; i<row; i++) {
        cin >> s;
        for (int j=0; j<col; j++)
            arr[i][j] = s[j];
    }

    for (int i=0; i<row; i++) {
        for (int j=0; j<col; j++) {
            if (arr[i][j] == '#') continue;
            for (int k=0; k<dir_row.size(); k++) {
                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 ++) {
                    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.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: 372092