#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 

using namespace std;
using namespace __gnu_pbds; 
  
#define ll long long
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update> 

#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
	enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
	ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
	*this << "[";
	for (auto it = d.b; it != d.e; ++it)
		*this << ", " + 2 * (it == d.b) << *it;
	ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

const int MOD = (int)1e9 + 7;
const int MX = (int)1e5 + 10;

void add_self(int &x, int y, int md = MOD){x += y; if(x >= md) x -= md;}
void sub_self(int &x, int y, int md = MOD){x -= y; if(x < 0) x += md;}
void mul_self(int &x, int y, int md = MOD){x = x * 1LL * y % md;}
inline int mul(int x, int y, int md = MOD){return x * 1LL * y % md;}
inline int add(int x, int y, int md = MOD){x += y; if(x >= md) x -= md; return x;}
inline int sub(int x, int y, int md = MOD){x -= y; if(x < 0) x += md; return x;}

const int dx[] = {0, 0, -1, 1};
const int dy[] = {1, -1, 0, 0};
	
void pre(){
}	

void solve(){
	int h, w, srcx, srcy, desx, desy;
	cin >> h >> w >> srcx >> srcy >> desx >> desy;
	--srcx, --srcy, --desx, --desy;
	vector<vector<char>> vec(h, vector<char>(w));
	for(auto &rw : vec) for(auto &c : rw) cin >> c;

	auto ok = [&](int xx, int yy){
		return xx >= 0 && xx < h && yy >= 0 && yy < w && vec[xx][yy] != '#';
	};

	vector<vector<int>> dist(h, vector<int>(w, 1e9));
	dist[srcx][srcy] = 0;
	deque<array<int, 2>> q;
	q.push_front({srcx, srcy});

	while(!q.empty()){
		auto p = q.front();
		q.pop_front();
      	if(p[0] == desx && p[1] == desy){
          cout << dist[p[0]][p[1]] << '\n';
          return;
        }
		for(int i = 0; i < 4; ++i){
			int xx = p[0] + dx[i];
			int yy = p[1] + dy[i];
			if(ok(xx, yy) && dist[xx][yy] > dist[p[0]][p[1]]){
				dist[xx][yy] = dist[p[0]][p[1]];
				q.push_front({xx, yy});
			}
		}
		for(int i = -2; i <= 2; ++i){
			for(int j = -2; j <= 2; ++j){
				int xx = p[0] + i;
				int yy = p[1] + j;
				if(ok(xx, yy) && dist[xx][yy] > dist[p[0]][p[1]] + 1){
					dist[xx][yy] = dist[p[0]][p[1]] + 1;
					q.push_back({xx, yy});
				}
			}
		}
	}

	int res = dist[desx][desy];
	if(res == (int)1e9) res = -1;
	cout << res << "\n";
	
	return;
}

int main(){

	cin.tie(0); cout.tie(0);
	ios_base::sync_with_stdio(0);

	// freopen("input.in", "r", stdin);
	// freopen("output.out", "w", stdout);

	int t;
	t = 1;
	// cin >> t;
	// pre();
	for(int i = 1; i <= t; ++i){
		// cout << "Case #" << i << ": ";
		solve();
		// cout << '\n';
		// cout << endl;
	}

	return 0;
}


Measured memory_bytes: 8628