using System;
using System.Text;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using E = System.Linq.Enumerable;
using System.IO.Pipes;
using System.Threading;

class Program
{
    static char[] abc = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
    static long mod = 1000000007;
    static long H;
    static long W;
    static long SY;
    static long GY;
    static long SX;
    static long GX;
    static long ans;
    static String[] map;
    static long[][] used;
    static void Main(string[] args)
    {
        //var S = Console.ReadLine();
        //var N = long.Parse(Console.ReadLine());
        //var N = long.Parse(Console.ReadLine());
        var HW = Console.ReadLine().Split(' ').Select(x => long.Parse(x)).ToArray();
        H = HW[0];
        W = HW[1];
        var C = Console.ReadLine().Split(' ').Select(x => long.Parse(x)).ToArray();
        var D = Console.ReadLine().Split(' ').Select(x => long.Parse(x)).ToArray();

        SX = C[0];
        SY = C[1];

        GX = D[0];
        GY = D[1];
        map = new string[H];
        used = new long[H][];

        for (int i = 0; i < H; i++)
        {
            used[i] = new long[W];
            map[i] = Console.ReadLine();
        }
        for (int i = 0; i < H; i++)
        {
            for (int j = 0; j < W; j++)
            {
                used[i][j] = long.MaxValue;
            }
        }
        var que = new Queue<Tuple<long, long>>();
        que.Enqueue(new Tuple<long, long>(SX - 1,SY - 1));
        used[SX - 1][SY - 1] = 1;
        WFS(que);

        

        Console.WriteLine(used[GX - 1][GY - 1] == long.MaxValue ? -1 : used[GX - 1][GY - 1] - 1);

    }

    static void WFS(Queue<Tuple<long, long>> next,long count = 1)
    {
        
        var que = new Queue<Tuple<long, long>>(next);
        var que2 = new Queue<Tuple<long, long>>(next);

        

        while (que.Count() > 0)
        {
            var top = que.Dequeue();

            if(top.Item1 + 1 < H && used[top.Item1 + 1][top.Item2] > count && map[top.Item1 + 1][(int)top.Item2] == '.')
            {
                que.Enqueue(new Tuple<long, long>(top.Item1 + 1, top.Item2));
                que2.Enqueue(new Tuple<long, long>(top.Item1 + 1, top.Item2));
                used[top.Item1 + 1][top.Item2] = count;
            }

            if (top.Item2 + 1 < W && used[top.Item1][top.Item2 + 1] > count && map[top.Item1][(int)top.Item2 + 1] == '.')
            {
                que.Enqueue(new Tuple<long, long>(top.Item1, top.Item2 + 1));
                que2.Enqueue(new Tuple<long, long>(top.Item1, top.Item2 + 1));
                used[top.Item1][top.Item2 + 1] = count;
            }

            if (top.Item1 - 1 >= 0 && used[top.Item1 - 1][top.Item2] > count && map[top.Item1 - 1][(int)top.Item2] == '.')
            {
                que.Enqueue(new Tuple<long, long>(top.Item1 - 1, top.Item2));
                que2.Enqueue(new Tuple<long, long>(top.Item1 - 1, top.Item2));
                used[top.Item1 - 1][top.Item2] = count;
            }

            if (top.Item2 - 1 >= 0 && used[top.Item1][top.Item2 - 1] > count && map[top.Item1][(int)top.Item2 - 1] == '.')
            {
                que.Enqueue(new Tuple<long, long>(top.Item1, top.Item2 - 1));
                que2.Enqueue(new Tuple<long, long>(top.Item1, top.Item2 - 1));
                used[top.Item1][top.Item2 - 1] = count;
            }
        }



        //var OriginalQue2Count = que2.Count();
        var next2 = new Queue<Tuple<long, long>>();
        while (que2.Count() > 0)
        {
            var top = que2.Dequeue();

            for (int i = -2; i <= 2; i++)
            {
                if (IsOk(top.Item1 + 2, top.Item2 + i) && used[top.Item1 + 2][top.Item2 + i] > count + 1 && map[top.Item1 + 2][(int)top.Item2 + i] == '.')
                {
                    used[top.Item1 + 2][top.Item2 + i] = count + 1;
                    next2.Enqueue(new Tuple<long, long>(top.Item1 + 2, top.Item2 + i));
                }
            }


            for (int i = -2; i <= 2; i++)
            {
                if (IsOk(top.Item1 + 1, top.Item2 + i) && used[top.Item1 + 1][top.Item2 + i] > count + 1 && map[top.Item1 + 1][(int)top.Item2 + i] == '.')
                {
                    used[top.Item1 + 1][top.Item2 + i] = count + 1;
                    next2.Enqueue(new Tuple<long, long>(top.Item1 + 1, top.Item2 + i));
                }
            }

            for (int i = -2; i <= 2; i++)
            {
                if (IsOk(top.Item1, top.Item2 + i) && used[top.Item1][top.Item2 + i] > count + 1 && map[top.Item1][(int)top.Item2 + i] == '.')
                {
                    used[top.Item1][top.Item2 + i] = count + 1;
                    next2.Enqueue(new Tuple<long, long>(top.Item1, top.Item2 + i));
                }
            }

            for (int i = -2; i <= 2; i++)
            {
                if (IsOk(top.Item1 - 1, top.Item2 + i) && used[top.Item1 - 1][top.Item2 + i] > count + 1 && map[top.Item1 - 1][(int)top.Item2 + i] == '.')
                {
                    used[top.Item1 - 1][top.Item2 + i] = count + 1;
                    next2.Enqueue(new Tuple<long, long>(top.Item1 - 1, top.Item2 + i));
                }
            }

            for (int i = -2; i <= 2; i++)
            {
                if (IsOk(top.Item1 - 2, top.Item2 + i) && used[top.Item1 - 2][top.Item2 + i] > count + 1 && map[top.Item1 - 2][(int)top.Item2 + i] == '.')
                {
                    used[top.Item1 - 2][top.Item2 + i] = count + 1;
                    next2.Enqueue(new Tuple<long, long>(top.Item1 - 2, top.Item2 + i));
                }
            }
        }

        if (next2.Count() > 0) WFS(next2, count + 1);

    }


    static bool IsOk(long p, long q)
    {
        if (p >= H || q >= W)
        {
            return false;
        }

        if (p < 0 || q < 0)
        {
            return false;
        }

        return true;
    }



}


public class PriorityQueue<T> : IEnumerable<T>
{
    private readonly List<T> _data = new List<T>();
    private readonly IComparer<T> _comparer;
    private readonly bool _isDescending;

    public PriorityQueue(IComparer<T> comparer, bool isDescending = true)
    {
        _comparer = comparer;
        _isDescending = isDescending;
    }

    public PriorityQueue(Comparison<T> comparison, bool isDescending = true)
        : this(Comparer<T>.Create(comparison), isDescending)
    {
    }

    public PriorityQueue(bool isDescending = true)
        : this(Comparer<T>.Default, isDescending)
    {
    }

    public void Enqueue(T item)
    {
        _data.Add(item);
        var childIndex = _data.Count - 1;
        while (childIndex > 0)
        {
            var parentIndex = (childIndex - 1) / 2;
            if (Compare(_data[childIndex], _data[parentIndex]) >= 0)
                break;
            Swap(childIndex, parentIndex);
            childIndex = parentIndex;
        }
    }

    public T Dequeue()
    {
        var lastIndex = _data.Count - 1;
        var firstItem = _data[0];
        _data[0] = _data[lastIndex];
        _data.RemoveAt(lastIndex--);
        var parentIndex = 0;
        while (true)
        {
            var childIndex = parentIndex * 2 + 1;
            if (childIndex > lastIndex)
                break;
            var rightChild = childIndex + 1;
            if (rightChild <= lastIndex && Compare(_data[rightChild], _data[childIndex]) < 0)
                childIndex = rightChild;
            if (Compare(_data[parentIndex], _data[childIndex]) <= 0)
                break;
            Swap(parentIndex, childIndex);
            parentIndex = childIndex;
        }
        return firstItem;
    }

    public T Peek()
    {
        return _data[0];
    }

    private void Swap(int a, int b)
    {
        var tmp = _data[a];
        _data[a] = _data[b];
        _data[b] = tmp;
    }

    private int Compare(T a, T b)
    {
        return _isDescending ? _comparer.Compare(b, a) : _comparer.Compare(a, b);
    }

    public int Count => _data.Count;

    public IEnumerator<T> GetEnumerator()
    {
        return _data.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

Measured memory_bytes: 171088