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

// DEBUG BEGIN
#ifdef LOCAL
template<typename L, typename R> ostream &operator<<(ostream &out, const pair<L, R> &p){
	return out << "(" << p.first << ", " << p.second << ")";
}
template<typename Tuple, size_t N> struct TuplePrinter{
	static ostream &print(ostream &out, const Tuple &t){ return TuplePrinter<Tuple, N-1>::print(out, t) << ", " << get<N-1>(t); }
};
template<typename Tuple> struct TuplePrinter<Tuple, 1>{
	static ostream &print(ostream &out, const Tuple& t){ return out << get<0>(t); }
};
template<typename... Args> ostream &print_tuple(ostream &out, const tuple<Args...> &t){
	return TuplePrinter<decltype(t), sizeof...(Args)>::print(out << "(", t) << ")";
}
template<typename ...Args> ostream &operator<<(ostream &out, const tuple<Args...> &t){
	return print_tuple(out, t);
}
template<typename T> ostream &operator<<(enable_if_t<!is_same<T, string>::value, ostream> &out, const T &arr){
	out << "{"; for(auto &x: arr) out << x << ", ";
	return out << (arr.size() ? "\b\b" : "") << "}";
}
template<size_t S> ostream &operator<<(ostream &out, const bitset<S> &b){
	for(int i = 0; i < S; ++ i) out << b[i];
	return out;
}
void debug_out(){ cerr << "\b\b " << endl; }
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){ cerr << H << ", ", debug_out(T...); }
void debug2_out(){ cerr << "-----DEBUG END-----\n"; }
template<typename Head, typename... Tail>
void debug2_out(Head H, Tail... T){ cerr << "\n"; for(auto x: H) cerr << x << "\n"; debug2_out(T...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__)
#define debug2(...) cerr << "----DEBUG BEGIN----\n[" << #__VA_ARGS__ << "]:", debug2_out(__VA_ARGS__)
#else
#define debug(...) 42
#define debug2(...) 42
#endif
// DEBUG END

int main(){
	cin.tie(0)->sync_with_stdio(0);
	int h, w, ch, cw, dh, dw;
	cin >> h >> w >> ch >> cw >> dh >> dw, -- ch, -- cw, -- dh, -- dw;
	vector<string> a(h);
	for(auto &s: a){
		cin >> s;
	}
	static const int inf = numeric_limits<int>::max();
	vector<vector<int>> dist(h, vector<int>(w, inf));
	dist[ch][cw] = 0;
	deque<array<int, 3>> q{{{ch, cw, 0}}};
	static const vector<pair<int, int>> dr{{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
	auto inrange = [&](int x, int y){
		return 0 <= x && x < h && 0 <= y && y < w;
	};
	while(!q.empty()){
		auto [x, y, d] = q.front(); q.pop_front();
		debug(x, y, d);
		if(d == dist[x][y]){
			for(auto [dx, dy]: dr){
				int nx = x + dx, ny = y + dy;
				if(inrange(nx, ny) && a[nx][ny] == '.' && dist[nx][ny] > d){
					q.push_front({nx, ny, dist[nx][ny] = d});
				}
			}
			for(auto dx = -2; dx <= 2; ++ dx){
				for(auto dy = -2; dy <= 2; ++ dy){
					int nx = x + dx, ny = y + dy;
					if(inrange(nx, ny) && a[nx][ny] == '.' && dist[nx][ny] > d + 1){
						q.push_back({nx, ny, dist[nx][ny] = d + 1});
					}
				}
			}
		}
	}
	debug(dist);
	dist[dh][dw] < inf ? cout << dist[dh][dw] << "\n" : cout << "-1\n";
	return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                    //
//                                   Coded by Aeren                                   //
//                                                                                    //
////////////////////////////////////////////////////////////////////////////////////////


Measured memory_bytes: 8800