#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <string>
#include <algorithm>
#include <iomanip>
#include <cmath>
#include <cstring>
#include <tuple>

std::string* S = nullptr;
std::vector<int> data;
int H, W;

void fill(int h, int w, int area)
{
	if (h < 0 || h >= H || w < 0 || w >= W) {
		return;
	}
	const int index = W * h + w;
	if (data[index] == 0 && S[h][w] == '.') {
		data[index] = area;
		fill(h - 1, w, area);
		fill(h, w-1, area);
		fill(h + 1, w, area);
		fill(h, w + 1, area);
	}
}

int main()
{
	std::cin >> H >> W;
	int Ch, Cw;
	std::cin >> Ch >> Cw;
	int Dh, Dw;
	std::cin >> Dh >> Dw;
	S = new std::string[H];
	for (int i = 0; i < H; ++i) {
		std::cin >> S[i];
	}

	data.resize( H*W,0 );
	int area = 0;
	for (int w = 0; w < W; ++w) {
		for (int h = 0; h < H; ++h) {
			if (S[h][w] == '.')
			{
				const int index = W * h + w;
				if (data[index] == 0) {
					area++;
					fill(h, w, area);
				}
			}
		}
	}

	typedef std::multimap<int, int> MAP;
	MAP route;
	for (int w = 0; w < W; ++w) {
		for (int h = 0; h < H; ++h) {
			const int start_area = data[W*h+w];
			if (start_area > 0) {
				for (int i = -2; i <= +2; ++i) {
					for (int j = -2; j <= +2; ++j) {
						if (w + i >= 0 && w + i < W && h + j >= 0 && h + j < H) {
							const int area = data[W*(h+j) + w + i];
							if (area > 0 && area != start_area) {
								route.insert(MAP::value_type(start_area, area));
								route.insert(MAP::value_type(area, start_area));
							}
						}
					}
				}
			}
		}
	}

	const int start_area = data[W*(Ch-1)+Cw-1];
	std::set<int> used;
	used.insert(start_area);
	std::set<int> from;
	from.insert(start_area);
	std::set<int> to;
	int warp = 0;
	const int target_area = data[W*(Dh - 1) + Dw - 1];
	while (true) {
		bool found = false;
		for (auto itr = from.begin(); itr != from.end(); ++itr) {
			if (*itr == target_area) {
				found = true;
				break;
			}
			auto range = route.equal_range(*itr);
			for (auto range_itr = range.first; range_itr != range.second; ++range_itr) {
				to.insert(range_itr->second);
			}
		}
		if (found) {
			break;
		}
		from.clear();
		for (auto itr = to.begin(); itr != to.end(); ++itr) {
			if (used.find(*itr) == used.end()) {
				used.insert(*itr);
				from.insert(*itr);
			}
		}
		if (from.empty()) {
			warp = -1;
			break;
		}
		to.clear();
		warp++;
	}

	std::cout << warp << std::endl;

	delete[] S;


	/*
	int H, W, M;
	std::cin >> H >> W >> M;
	typedef std::set<std::pair<int, int>> SET;
	SET B;
	std::vector<int> count_h(H,0);
	std::vector<int> count_w(W, 0);
	for (int i = 0; i < M; ++i) {
		int h, w;
		std::cin >> h >> w;
		count_h[h - 1] += 1;
		count_w[w - 1] += 1;
		B.insert(SET::value_type(h, w));
	}

	int max_count_h = 0;
	for (int h = 1; h <= H; ++h) {
		if (count_h[h - 1] > max_count_h) {
			max_count_h = count_h[h - 1];
		}
	}

	int max_count_w = 0;
	for (int w = 1; w <= W; ++w) {
		if (count_w[w - 1] > max_count_w) {
			max_count_w = count_w[w - 1];
		}
	}

	bool found = false;
	for (int h = 1; h <= H; ++h) {
		if (count_h[h - 1] == max_count_h) {
			for (int w = 1; w <= W; ++w) {
				if (count_w[w - 1] == max_count_w) {
					if (B.find(SET::value_type(h, w)) == B.end()) {
						found = true;
						break;
					}
				}
			}
			if (found) {
				break;
			}
		}
	}

	if (found) {
		std::cout << max_count_h + max_count_w << std::endl;
	}
	else {
		std::cout << max_count_h + max_count_w-1 << std::endl;

	}
	*/

	return 0;
}

Measured memory_bytes: 187864