#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)   FOR(i,0,n)
#define ALL(obj)   (obj).begin(),(obj).end()

#define debug(var)  do{std::cout << __LINE__ << "> " << #var << ": ";view(var);}while(0)
template<typename T> void view(T e){std::cout << e << std::endl;}
template<typename T> void view(const std::vector<T>& v){for(const auto& e : v){ std::cout << e << " "; } std::cout << std::endl;}
template<typename T> void view(const std::vector<std::vector<T> >& vv){ for(const auto& v : vv){ view(v); } }

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

using namespace std;
using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<ll>>;

// 4 近傍
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

struct Dijkstra {
    struct edge{
        int to;
        long long cost;
        edge(int to, long long cost) : to(to), cost(cost) { }
    };
    typedef pair< long long, int > P;
    const long long INF = 1LL<<60;
    int v;
    int s;
    vector< vector < edge > > g;
    vector< long long > dist;
    priority_queue< P, vector< P >, greater< P > > que;
    Dijkstra(int v, int s) : v(v), s(s), g(v), dist(v, INF) {
        dist[s] = 0;
        que.push(P(0, s));
    }
    void add_edge(int start, int to, long long cost) {
        g[start].emplace_back(to, cost);
    }
    void build() {
        while (!que.empty()) {
            P p = que.top(); que.pop();
            int current = p.second;
            if (dist[current] < p.first) continue;
            for (edge& e : g[current]) {
                if (dist[e.to] > dist[current] + e.cost) {
                    dist[e.to] = dist[current] + e.cost;
                    que.push(P(dist[e.to], e.to));
                }
            }
        }
    }
    long long shortest_path_value(int t) {
        return dist[t] >= INF ? -1 : dist[t];
    }
};

void Main() {
	int H, W, CH, CW, DH, DW; cin >> H >> W >> CH >> CW >> DH >> DW;
	--CH, --CW, --DH, --DW;
	vector<string> S(H);
	vector<string> _S(H);
	REP(i,H) {
		cin >> S[i];
		_S[i] = S[i];
	}
	vvi SIdx(H, vi(W, -1));

	auto dfs = [&](auto dfs, int x, int y, int idx) -> void {
		_S[y][x] = '#';
		SIdx[y][x] = idx;
		REP(i, 4) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			if (0 <= nx && nx < W && 0 <= ny && ny < H && _S[ny][nx] == '.') {
				dfs(dfs, nx, ny, idx);
			}
		}
    };

	int idx = -1;
	REP(i,H) {
		REP(j,W) {
			if (_S[i][j] == '.') {
				++idx;
				dfs(dfs, j, i, idx);
			}
		}
	}

	// debug(SIdx);

	int nodeNum = idx + 1;
	vector<set<int>> nodeSet(nodeNum);
	REP(i,H) {
		REP(j,W) {
			int currentIdx = SIdx[i][j];
			if (currentIdx == -1) continue;
			FOR(k,-2,3) {
				FOR(l,-2,3) {
					int nx = j + l;
					int ny = i + k;
					if (0 > nx || nx >= W || 0 > ny || ny >= H) continue;
					if (SIdx[ny][nx] == -1) continue;
					if (SIdx[ny][nx] != SIdx[i][j]) {
						nodeSet[currentIdx].insert(SIdx[ny][nx]);
					}
				}
			}
		}
	}
	Dijkstra dijkstra(nodeNum, SIdx[CH][CW]);
	REP(i,nodeNum) {
		for (auto neighbor : nodeSet[i]) {
			dijkstra.add_edge(i, neighbor, 1);
		}
	}
    dijkstra.build();
	cout << dijkstra.shortest_path_value(SIdx[DH][DW]) << endl;
}

int main() {
    cin.tie(nullptr);
	ios_base::sync_with_stdio(false);
	cout << fixed << setprecision(15);
	Main();
}


Measured memory_bytes: 46716