#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <tuple>
#include <utility>


using namespace std;
// import sys, math, heapq
#define MAX_V 1000
#define MAX_W 1000
#define INF pow(10, 6)
typedef priority_queue<tuple<int,int,int>, vector< tuple<int, int, int> >, greater< tuple<int, int, int> > > PQ;

// int dist[MAX_V][MAX_W];



void move(int V, int W, int start[2], int goal[2], vector<string> Maps)
{
    vector< vector<int> > dist(V, vector<int>(W, INF));
    PQ Queue;
    // Queue.push( make_tuple(0, start[0], start[1]) );
    Queue.emplace( 0, start[0], start[1] );
    dist[start[1]][start[0]] = 0;

    vector< pair<int, int> > move_walk= { make_pair(-1, 0), make_pair(1, 0), make_pair(0, -1), make_pair(0, 1) };
    /*
    pair<int, int> p = move_walk[1];
    cout << p.first << " " << p.second << endl;
    */
    while( !Queue.empty() )
    {
        // auto [distance, x, y] = Queue.top(); Queue.pop();
        auto pos= Queue.top(); Queue.pop();
        int distance = get<0>(pos), x = get<1>(pos), y = get<2>(pos);

        if(x==goal[0] && y == goal[1]){
            cout << dist[y][x] << endl;
            exit(0);
        }

        if(distance > dist[y][x]) continue;


        int flag = -1;
        int N_flag = 0;
        for(int i=0; i<4; i++)
        {
            int x_next = x+move_walk[i].first, y_next = y+move_walk[i].second;
            if(x_next < 0 || x_next > W-1 || y_next < 0 || y_next > V-1) continue;
            if(Maps[y_next][x_next] == '#')
            {
                flag = i;
                N_flag ++;
                continue;
            }
            if(dist[y_next][x_next] > dist[y][x])
            {
                dist[y_next][x_next] = dist[y][x];
                Queue.push( make_tuple(dist[y_next][x_next], x_next, y_next) );

            }

        }

        if(N_flag > 1)
        {
            int dy_min = max(-y, -2), dy_max = min(V-y, 3);
            int dx_min = max(-x, -2), dx_max = min(W-x, 3);
            for(int dy=dy_min; dy< dy_max; dy++)
            {
                for(int dx=dx_min; dx< dx_max; dx++)
                {
                    int x_next = x+dx, y_next = y+dy;
                    if(Maps[y_next][x_next] == '.' && dist[y_next][x_next] == INF)
                    {
                        dist[y_next][x_next] = dist[y][x]+1;
                        Queue.push( make_tuple(dist[y_next][x_next], x_next, y_next) );
                    }

                }
            }

        }
        else if(flag > -1)
        {
            int dy_min = max(-y, -2), dy_max = min(V-y, 3);
            int dx_min = max(-x, -2), dx_max = min(W-x, 3);
            // make_pair(-1, 0), make_pair(1, 0), make_pair(0, -1), make_pair(0, 1)
            if(flag == 3) dy_min = 1;
            else if(flag==2) dy_max = 0;
            else if(flag==1) dx_min = 1;
            else dx_max = 0;
            for(int dy=dy_min; dy< dy_max; dy++)
            {
                for(int dx=dx_min; dx< dx_max; dx++)
                {
                    int x_next = x+dx, y_next = y+dy;
                    if(Maps[y_next][x_next] == '.' && dist[y_next][x_next] == INF)
                    {
                        dist[y_next][x_next] = dist[y][x]+1;
                        Queue.push( make_tuple(dist[y_next][x_next], x_next, y_next) );
                    }

                }
            }

        }





    }
    if( dist[goal[1]][goal[0]] == INF )
    {
        cout << -1 << endl;
    }
    return;
}



int main(void)
{
    // int dist[][MAX_W], stack1 stack_walk, stack1 stack_warp;
    int V1, W1;
    cin >> V1 >> W1; // x, y
    const int V = V1;
    const int W = W1;
    int start[2], goal[2]; // [x, y]
    cin >> start[1] >> start[0] >> goal[1] >> goal[0];

    start[0] --;
    start[1] --;
    goal[0] --;
    goal[1] --;
    // char Maps[V][W];
    // vector<string> Maps;
    vector<string> Maps;
    string str;
    for(int i=0; i<V; i++)
    {
        cin >> str;
        Maps.push_back(str);
    }

    // vector< vector<int> > dist(V, vector<int>(W, INF));



    move(V, W, start, goal, Maps);

    /*
    while(true)
    {
        move(V, W, goal, Maps, dist, stack_walk, stack_warp);

        if( dist[goal[1]][goal[0]] < INF )
        {
            cout << dist[goal[1]][goal[0]] << endl;
            break;
        }
        else if(stack_warp.empty())
        {
            cout << -1 << endl;
            break;
        }
        swap(stack_walk, stack_warp);

    }
    */



    return 0;
}


Measured memory_bytes: 9808