using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using static System.Console;
using static System.Math;
using static MyIO;
using static MyUtil;
using static ShortestPath;

public class D { public static void Main() => (new Solver()).Solve(); }

public class Solver
{
	private long[] dy = new long[] { -1, 0, 1, 0 };
	private long[] dx = new long[] { 0, -1, 0, 1 };

	public void Solve()
	{
		long H = GetLong();
		long W = GetLong();
		var C = (GetLong() - 1, GetLong() - 1);
		var D = (GetLong() - 1, GetLong() - 1);
		var grid = new char[H, W];
		for(long i = 0; i < H; i++)
		{
			var S = GetString().ToArray();
			for(long j = 0; j < W; j++)
				grid[i, j] = S[j];
		}
		long conv(long y, long x) => y * W + x;

		var uf = new UnionFind(H * W);
		for(long i = 0; i < H; i++)
		{
			for(long j = 0; j < W; j++)
			{
				if(grid[i, j] == '#')
					continue;

				long v = conv(i, j);
				for(long k = 0; k < 4; k++)
				{
					var (ni, nj) = (i + dy[k], j + dx[k]);
					if(ni < 0 || ni >= H || nj < 0 || nj >= W || grid[ni, nj] == '#')
						continue;
					
					long u = conv(ni, nj);
					if(!uf.IsSame(v, u))
						uf.Unite(v, u);
				}
			}
		}

		var adj = Range(0, H * W).Select(_ => new List<Edge<long>>()).ToArray();
		for(long i = 0; i < H; i++)
		{
			for(long j = 0; j < W; j++)
			{
				if(grid[i, j] == '#')
					continue;

				long v = conv(i, j);
				long rv = uf.Root(v);
				for(long k = -2; k <= 2; k++)
				{
					for(long l = -2; l <= 2; l++)
					{
						var (ni, nj) = (i + k, j + l);
						if(ni < 0 || ni >= H || nj < 0 || nj >= W || grid[ni, nj] == '#')
							continue;

						long u = conv(ni, nj);
						long ru = uf.Root(u);
						adj[rv].Add(new Edge<long>(rv, ru, 1));
						adj[ru].Add(new Edge<long>(ru, rv, 1));
					}
				}
			}
		}

		long INF = long.MaxValue / 2;
		long s = conv(C.Item1, C.Item2);
		var d = Dijkstra<long>(adj, INF, uf.Root(s), (x, y) => x + y);
		long t = conv(D.Item1, D.Item2);
		WriteLine(d[uf.Root(t)] < INF ? d[uf.Root(t)] : -1);
	}
}

public static class ShortestPath
{
	public struct Edge<T>
	{
		public long From;
		public long To;
		public T Cost;

		public Edge(long from, long to, T cost)
		{
			From = from;
			To = to;
			Cost = cost;
		}
	}
	
	// false: has negative cycle
	public static bool BellmanFord<T>(long N, List<Edge<T>> edges, long s, T inf, Func<T, T, T> add, out T[] d) where T : IComparable<T>
	{
		d = Enumerable.Repeat(inf, (int)N).ToArray();
		d[s] = default(T);
		for(long i = 0; i < N; i++)
		{
			bool update = false;
			foreach(var e in edges)
			{
				var tmp = add(d[e.From], e.Cost);
				if((d[e.From].CompareTo(inf) < 0) && (d[e.To].CompareTo(tmp) > 0))
				{
					d[e.To] = tmp;
					update = true;
					if(i == N - 1)
						return false;
				}
			}
			if(!update)
				break;
		}
		return true;
	}

	public static bool HasNegativeCycle<T>(long N, List<Edge<T>> edges, Func<T, T, T> add) where T : IComparable<T>
	{
		var d = new T[N];		
		for(long i = 0; i < N; i++)
		{
			foreach(var e in edges)
			{
				var tmp = add(d[e.From], e.Cost);
				if(d[e.To].CompareTo(tmp) > 0)
				{
					d[e.To] = tmp;
					if(i == N - 1)
						return true;
				}
			}
		}
		return false;
	}

	public static T[] Dijkstra<T>(T[,] cost, T inf, long s, Func<T, T, T> add) where T : IComparable<T>
	{
		long V = cost.GetLength(0);	
		var used = new bool[V];
		var d = Enumerable.Repeat(inf, (int)V).ToArray();
		d[s] = default(T);

		while(true)
		{
			long v = -1;
			for(long u = 0; u < V; u++)
				if(!used[u] && (v == -1 || d[u].CompareTo(d[v]) < 0))
					v = u;

			if(v == -1)
				break;

			used[v] = true;
			for(long u = 0; u < V; u++)
			{
				var tmp = add(d[v], cost[v, u]);
				if(d[u].CompareTo(tmp) > 0)
					d[u] = tmp;
			}
		}
		return d;
	}

	public static T[] Dijkstra<T>(List<Edge<T>>[] adj, T inf, long s, Func<T, T, T> add) where T : IComparable<T>
	{
		Comparison<Tuple<T, long>> comp = ((x, y) => x.Item1.CompareTo(y.Item1));
		var pq = new PriorityQueue<Tuple<T, long>>(adj.Length, comp);

		var d = Enumerable.Repeat(inf, adj.Length).ToArray();
		d[s] = default(T);
		pq.Push(Tuple.Create(d[s], s));
		while(pq.Count > 0)
		{
			var p = pq.Pop();
			long v = p.Item2;
			if(d[v].CompareTo(p.Item1) < 0)
				continue;

			for(long i = 0; i < adj[v].Count; i++)
			{
				var edge = adj[v][(int)i];
				var tmp = add(d[v], edge.Cost);
				if(d[edge.To].CompareTo(tmp) > 0)
				{
					d[edge.To] = tmp;
					pq.Push(Tuple.Create(d[edge.To], edge.To));
				}
			}
		}
		return d;
	}

	// false: has negative cycle
	public static bool WarshallFloyd<T>(ref T[,] d, Func<T, T, T> add) where T : IComparable<T>
	{
		long V = d.GetLength(0);
		for(long k = 0; k < V; k++)
		{
			for(long i = 0; i < V; i++)
			{
				for(long j = 0; j < V; j++)
				{
					var tmp = add(d[i, k], d[k, j]);
					if(d[i, j].CompareTo(tmp) > 0)
						d[i, j] = tmp;
				}
			}
		}
		for(long i = 0; i < V; i++)
		{
			if(d[i, i].CompareTo(default(T)) < 0)
				return false;
		}
		return true;
	}
}

public class PriorityQueue<T>
{
	public long Count { get; private set; } = 0;
	public long MaxSize { get; private set; } = 0;
	private T[] m_heap;
	private Comparison<T> Comp = null;
	
	public PriorityQueue(long maxSize, Comparison<T> comp)
	{
		if(maxSize <= 0)
			throw new Exception();
		MaxSize = maxSize;
		m_heap = new T[maxSize];

		Comp = comp;
	}
	
	public void Push(T x)
	{
		if(Count == MaxSize)
		{
			T[] new_heap = new T[MaxSize << 1];
			Array.Copy(m_heap, new_heap, MaxSize);
			m_heap = new_heap;
			MaxSize <<= 1;
		}
		
		long i = Count++;
		while(i > 0)
		{
			long p = (i - 1)/2;
			if(Comp(m_heap[p], x) <= 0)
				break;
			m_heap[i] = m_heap[p];
			i = p;			
		}
		m_heap[i] = x;		
	}
	
	public T Pop()
	{
		if(Count == 0)
			throw new Exception("Queue is empty.");
		
		T result = m_heap[0];
		T x = m_heap[--Count];
		long i = 0;
		while(i * 2 + 1 < Count)
		{
			long c1 = i * 2 + 1, c2 = i * 2 + 2;
			if(c2 < Count && Comp(m_heap[c2], m_heap[c1]) < 0)
				c1 = c2;
			if(Comp(m_heap[c1], x) >= 0)
				break;
			m_heap[i] = m_heap[c1];
			i = c1;
		}
		m_heap[i] = x;
		
		return result;		
	}
	
	public T Peek() => m_heap[0];
}

public class UnionFind
{
	private long[] par = null;
	private long[] rank = null;
	private long[] size = null;
	
	public long Size(long x) => size[Root(x)];
	public bool IsSame(long x, long y) => (Root(x) == Root(y));

	public UnionFind(long n)
	{
		par = new long[n];
		rank = new long[n];
		size = new long[n];
		for(long i = 0; i < n; i++)
		{
			par[i] = i;
			rank[i] = 0;
			size[i] = 1;
		}
	}

	public long Root(long x)
	{
		if(par[x] == x)
			return x;

		long r = Root(par[x]);
		par[x] = r;
		return r;
	}
	
	public bool Unite(long x, long y)
	{
		long rx = Root(x);
		long ry = Root(y);
		if(rx == ry)
			return false;
		
		if(rank[rx] < rank[ry])
		{
			long tmp = rx;
			rx = ry;
			ry = tmp;
		}
		else if(rank[rx] == rank[ry])
			rank[rx]++;

		par[ry] = rx;
		size[rx] = size[rx] + size[ry];
		return true;
	}
}

public static class MyIO
{
	private static string[] args = new string[0];
	private static int cnt = 0;
	private static IEnumerable<string> getArgs(long N) => Range(0, N).Select(_ => getArg());
	private static string getArg()
	{
		if(cnt == args.Length) { args = Console.ReadLine().Split(); cnt = 0; }
		return args[cnt++];
	}

	public static int GetInt() => int.Parse(getArg());
	public static long GetLong() => long.Parse(getArg());
	public static double GetDouble() => double.Parse(getArg());
	public static decimal GetDecimal() => decimal.Parse(getArg());
	public static string GetString() => getArg();
	public static char GetChar() => getArg()[0];
	public static int[] GetInts(long N) => getArgs(N).Select(int.Parse).ToArray();
	public static long[] GetLongs(long N) => getArgs(N).Select(long.Parse).ToArray();
	public static double[] GetDoubles(long N) => getArgs(N).Select(double.Parse).ToArray();
	public static decimal[] GetDecimals(long N) => getArgs(N).Select(decimal.Parse).ToArray();
	public static string[] GetStrings(long N) => getArgs(N).ToArray();
}

public static class MyUtil
{
	public static void chmax<T>(ref T x, T y) where T : IComparable<T> { if(x.CompareTo(y) < 0) x = y; }
	public static void chmin<T>(ref T x, T y) where T : IComparable<T> { if(x.CompareTo(y) > 0)	x = y; }
	public static void swap<T>(ref T x, ref T y) { T tmp = x; x = y; y = tmp; }
	public static long rightShift(long x, long y) => (x >> (int)y);
	public static long leftShift(long x, long y) => (x << (int)y);
	public static bool contains(long s, long x) => (rightShift(s, x) & 1L) == 1L;
	public static long gcd(long x, long y) => (y == 0) ? x : gcd(y, x % y);
	public static long lcm(long x, long y) => (x / gcd(x,y)) * y;	
	public static IEnumerable<int> Range(long start, long count) => Enumerable.Range((int)start, (int)count);
	public static void Sort(this List<string> source) => source.Sort(StringComparer.Ordinal);
}


Measured memory_bytes: 529624