//
// ABC176D
// URL : https://atcoder.jp/contests/abc176/tasks/abc176_d
// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Runtime.InteropServices.ComTypes;
using System.Collections.Specialized;
using System.Net.Http.Headers;
using System.Data.SqlTypes;

namespace AtCoder.Template.ABC176D
{
    class Solver
    {
        public static readonly long MOD_CONST = 1000000007;//(long)Math.Pow(10, 9) + 7;

        public static void Main(string[] args)
        {
            //出力高速化
            var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            Console.SetOut(sw);
            var solver = new Solver();
            solver.Solve();
            Console.Out.Flush();
        }
        public static int[] dx = new int[4] { 0, 0, -1, +1 };
        public static int[] dy = new int[4] { -1, +1, 0, 0 };
        public static int[] dwy = new int[24] { -2, -2, -2, -2,-2,
            -1, -1, -1, -1, -1,
            0,0,0,0,
            1,1,1,1,1,
            2,2,2,2,2 };
        public static int[] dwx = new int[24] { -2, -1, 0, 1, 2,
            -2, -1, 0, 1, 2,
            -2, -1,  1, 2,
            -2, -1, 0, 1, 2,
            -2, -1, 0, 1, 2 };
        static int H, W;
        static int Ch, Cw;
        static int Dh, Dw;
        static char[,] S;

        static readonly int INVALID_ID = -1;
        static readonly int UNKNWON_AREA_ID = 0;
        static readonly char WALL = '#';
        static readonly char ROAD = '.';
        public void Solve()
        {
            int[] HW = Console.ReadLine().Split(' ').Select(_inputStr => int.Parse(_inputStr)).ToArray();
            H = HW[0];
            W = HW[1];
            //魔法使いのマス
            int[] Chw = Console.ReadLine().Split(' ').Select(_inputStr => int.Parse(_inputStr)).ToArray();
            Ch = Chw[0]-1;
            Cw = Chw[1]-1;
            //ゴール
            int[] Dhw = Console.ReadLine().Split(' ').Select(_inputStr => int.Parse(_inputStr)).ToArray();
            Dh = Dhw[0]-1;
            Dw = Dhw[1]-1;

            S = new char[H,W];
            for(int h = 0; h < H; ++h)
            {
                string s = Console.ReadLine();
                for(int w = 0; w < W; ++w){
                    S[h, w] = s[w];
                }
            }
            Console.WriteLine(findAns());
        }




        public int findAns()
        {
            //スタートから開始して、ゴールを目指す
            var memo = new int[H, W];
            for (int h = 0; h < H; ++h)
            {
                for (int w = 0; w < W; ++w)
                {
                    memo[h, w] = int.MaxValue;
                }
            }
            var paintPoints = new List<int[]>();
            int sy = Ch;
            int sx = Cw;
            bfs(sy, sx, 0, ref memo, ref paintPoints);
            for (int cost = 0; ; ++cost)
            {
                //debugPrintCosts(ref memo);
                //コスト0でたどり着けるマスから、移動Bで行けて、まだコスト0以下でたどり着けないマスを列挙
                List<int[]> candidates = new List<int[]>();
                search(cost, paintPoints, ref memo, out candidates);
                paintPoints.Clear();

                if(candidates.Count == 0) { break; }
                int nextCost = cost + 1;
                foreach(var next in candidates)
                {
                    int y = next[0];
                    int x = next[1];
                    //もう探索済みならスキップ
                    if(memo[y,x] <= nextCost)
                    {
                        continue;
                    }
                    bfs(y, x, nextCost, ref memo, ref paintPoints);
                }
            }
            var goalCost = memo[Dh, Dw];
            return goalCost == int.MaxValue ? -1 : goalCost;
        }
        /// <summary>
        /// 開始位置から行ける場所を全部塗る(= costsにその場所へのコストを入れる)
        /// </summary>
        /// <param name="sy">開始位置</param>
        /// <param name="sx">開始位置</param>
        /// <param name="cost">塗りたくるcost</param>
        /// <param name="costs">その場所に移動するのに必要なコスト</param>
        /// <param name="paintPoints">先程新たに塗った場所メモ</param>
        public static void bfs(int sy, int sx, int cost,ref int[,] costs, ref List<int[]> paintPoints)
        {
            //今いる場所を初期化
            costs[sy, sx] = cost;
            paintPoints.Add(new int[2] { sy, sx });

            var nextPosQueue = new Queue<int[]>();
            nextPosQueue.Enqueue(new int[2] { sy, sx });
            while(nextPosQueue.Count > 0)
            {
                var next = nextPosQueue.Dequeue();
                int ny = next[0];
                int nx = next[1];
                for (int i = 0; i< 4; ++i)
                {
                    //移動先
                    int x = nx + dx[i];
                    int y = ny + dy[i];
                    if (x < 0 || W <= x) { continue; }
                    if (y < 0 || H <= y) { continue; }
                    //移動先が壁
                    if(S[y,x] == WALL) { continue; }
                    //もう行っているならパス
                    if(costs[y,x] <= cost) { continue; }
                    //まだ行ってないところ
                    costs[y, x] = cost;
                    var nextPoint = new int[2] { y, x };
                    paintPoints.Add(nextPoint);
                    nextPosQueue.Enqueue(nextPoint);
                }
            }
        }
        public static void search(int cost, List<int[]> paintPoints, ref int[,] costs, out List<int[]> candidates)
        {
            candidates = new List<int[]>();
            foreach(var point in paintPoints)
            {
                int h = point[0];
                int w = point[1];
                //移動Bで行ける場所をリストアップ
                for (int i = 0; i < 24; ++i)
                {
                    int x = w + dwx[i];
                    int y = h + dwy[i];
                    //移動不可能なところならスキップ
                    if (x < 0 || W <= x) { continue; }
                    if (y < 0 || H <= y) { continue; }
                    if (S[y, x] == WALL) { continue; }
                    //次の場所に行くのにかかるコストがcostより大きい場所なら候補に加えたい
                    //(例 : まだ調べてない場所とか。もう調べているなら、コストはcost以下のはず)
                    if(costs[y,x] <= cost) { continue; }//ここは、もう探索済み
                    //移動Bで行けて調べる場所の候補に加える
                    candidates.Add(new int[2] { y, x });
                }
            }
            return;
        }

        public static void debugPrintCosts(ref int[,] memo)
        {
            for (int h = 0; h < H; ++h)
            {
                for (int w = 0; w < W; ++w)
                {
                    var c = memo[h, w];
                    if (c != int.MaxValue)
                    {
                        Console.Write($"{c.ToString() } ");
                    }
                    else
                    {
                        Console.Write($". ");
                    }
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }


        //---------------------------------------------------------------------------------
        #region MyLib
        /// <summary>
        /// string -> List<char>に分解する。1文字がListの1要素
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        public static List<char> separeteToList(string a)
        {
            var l = new List<char>(a.Length);
            foreach (char x in a)
            {
                l.Add(x);
            }
            return l;
        }
        /// <summary>
        /// List<char> -> stringに合成する
        /// </summary>
        /// <param name="l"></param>
        /// <returns></returns>
        public static string combineCharList(List<char> l)
        {
            var ans = new StringBuilder();
            foreach (char x in l)
            {
                ans.Append(x);
            }
            return ans.ToString();
        }

        /// <summary>
        /// Aの文字をなるべくCorrectに合うように並びかえる。当然Correctにしかない文字もあるので、その場合はAの適当な文字で置き換える
        /// 例)
        /// A       = abcde, eppstein
        /// Corrent = acfbe, pipeline
        /// ans     = acdbe, pspetine
        /// </summary>
        /// <param name="A"></param>
        /// <param name="Correct"></param>
        public static List<char> FillChar(List<char> A, List<char> Correct)
        {
            char Empty = ' ';
            var ARemain = new List<char>(A);
            var ans = new List<char>(A.Count);
            for (int i = 0; i < Correct.Count; ++i)
            {
                //Aの文字をなるべくCorrectに合うように、ansの文字を決める
                int foundPos = ARemain.FindIndex(x => x == Correct[i]);
                if (foundPos != -1)//文字がCorrectの中で見つかったら
                {
                    char found = ARemain[foundPos];
                    ans.Add(found);
                    ARemain.Remove(found);//使った文字は除外
                }
                else//Aにない文字もある。後で使わなかったAの適当な文字で埋める
                {
                    ans.Add(Empty);
                }
            }
            //Aにない文字がCorrectにあったら、Aの残りの文字で適当に埋める
            for (int i = 0; i < A.Count; ++i)
            {
                if (ans[i] == Empty)
                {
                    ans[i] = ARemain.First();
                    ARemain.RemoveAt(0);
                }
            }
            return ans;
        }


        /// <summary>
        /// リストから、重複したものを除外したリストを新規に作成する
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="src"></param>
        /// <param name="dst"></param>
        public static void getDistinctList<T>(List<T> src, out List<T> dst)
        {
            var iter = src.Distinct();
            dst = new List<T>();
            foreach (var item in iter)
            {
                dst.Add(item);
            }
        }

        /// <summary>
        /// グラフ系
        /// </summary>
        public class Node
        {
            public Node(long val){
                this.Value = val;
                this.Children = new List<Node>();
            }

            public Node(long val, List<Node> children)
            {
                this.Value = val;
                this.Children = children;
            }

            public long Value { get; set; }
            public List<Node> Children { get; set; }
        }

        /// <summary>
        /// Clamping
        /// </summary>
        /// <typeparam name="T">比較型</typeparam>
        /// <param name="x">clampしたい値</param>
        /// <param name="min">最小値</param>
        /// <param name="max">最大値</param>
        /// <returns>clamp済みの値</returns>
        public static T Clamp<T>(T x, T min, T max) where T : IComparable<T>
        {
            if (x.CompareTo(min) < 0) { return min; }
            else if (x.CompareTo(max) > 0) { return max; }
            else return x;
            //return Math.Max(Math.Min(x, max), min);
        }

        /// <summary>
        /// 指定された底log_baseでの, 対数を計算
        /// </summary>
        /// <param name="x"></param>
        /// <param name="log_base">指定の底</param>
        /// <returns></returns>
        public static double LogBase(double x, double log_base)
        {
            //log_b(N) = log_a(N) / log_a(B)より
            return Math.Log(x) / Math.Log(log_base);
        }

        /// <summary>
        /// 初項a, 公差d, 項数nの数列の和
        /// </summary>
        /// <param name="n">求めたいところ</param>
        /// <returns>初項からxまで足した値</returns>
        static long SumSeries(long a, long d, long n)
        {
            return (2 * a + (n - 1) * d) * n / 2;
        }
        /// <summary>
        /// 累積和の配列を計算する
        /// Sum[ a[0], a[i] )がs[i+1]に入っている
        /// s[0]  : 0                //一切和を取らない場合
        /// s[1]  : ls[0]            //a[0]   + s[0] = a[0]
        /// s[2]  : ls[1] + s[1]     //a[1]   + a[0]
        /// ...
        /// s[N]  : ls[N-1] + s[N-1] //a[N-1] + ... + a[0]
        /// s[N+1]: ls[N] + s[N]     //a[N]   + ... + a[0]
        /// 
        /// 例: [1, 7)の和(a[1] + ... + a[6])
        /// s[1] = a[0] //[0, 1)
        /// s[7] = a[0] + a[1] + ... + a[6] //[0, 7)
        /// よってs[7] - s[1]);
        /// </summary>
        /// <param name="ls">計算したい配列</param>
        /// <returns>累積和配列</returns>
        static List<long> AggregateSumList(List<long> a)
        {
            var s = new List<long>(a.Count + 1);
            if (a.Count == 0)
            {
                return s;
            }
            s.Add(0);//s[0] = 0
            for (int i = 0; i < a.Count; ++i)
            {
                s.Add(a[i] + s[i]);
            }
            return s;
        }


        /// <summary>
        /// 与えられた数が素数かどうかを計算する
        /// </summary>
        /// <param name="num">対象数</param>
        /// <returns>true:素数, false:素数ではない(合成数)</returns>
        public static bool isPrime(int num)
        {
            if (num < 2) return false;
            else if (num == 2) return true;
            else if (num % 2 == 0) return false;

            double sqrtNum = Math.Sqrt(num);
            for (int i = 3; i <= sqrtNum; i += 2)
            {
                if (num % i == 0)
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 素因数分解
        /// </summary>
        /// <param name="n"></param>
        /// <returns>keyが素数、valueがその素数の登場回数</returns>
        public static Dictionary<long, long> PrimeFactorization(long n)
        {
            var result = new Dictionary<long, long>();
            //初めの素数2から割っていく
            for (long p = 2; p * p <= n; p++)
            {
                //割り切れないなら、素因数に含まれてない
                if (n % p != 0) continue;
                long count = 0;

                // 割り続ける
                while (n % p == 0)
                {
                    count++;
                    n /= p;
                }

                result[p] = count;
            }

            // 素数が残っている場合
            if (n != 1) result[n] = 1;
            return result;
        }


        /// <summary>
        /// 順列mPnを計算する
        /// </summary>
        /// <param name="m"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        public static long Permutation(long m, long n)
        {
            long ret = 1;
            for (var i = 0; i < n; ++i)
            {
                ret *= m - i;
            }
            return ret;
        }
        /// <summary>
        /// 組み合わせmCnを計算する
        /// </summary>
        /// <param name="m"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        public static long Combination(long m, long n)
        {
            if (m == n || n == 0)
            {
                return 1;
            }
            long ans = 1;
            for (var i = 1; i <= n; ++i)
            {
                ans = ans * (m - i + 1) / i;
            }
            return ans;
        }

        static long Gcd(long m, long n)
        {
            if (n == 0) return m;
            return Gcd(n, m % n);
        }

        static long Lcm(long m, long n)
        {
            var gcd = Gcd(m, n);
            //return (m * n) / gcd;
            return m / gcd * n;//桁あふれ対策
        }
        #endregion MyLib
    }
}



Measured memory_bytes: 55744