#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
using ll = long long;
const int INF = 100000000;
template<typename T>
using vec2 = vector<vector<T>>;
template<typename T>
using vec3 = vec2<vector<T>>;
template<typename T>
using vec4 = vec3<vector<T>>;
template<typename T>
using vec5 = vec4<vector<T>>;
template<typename T>
using vec6 = vec5<vector<T>>;
template<typename... T>
using Node = tuple<T...>;

class Edge{
    public:
    int from, to;
    ll cost;

    Edge(int from, int to, ll cost): from(from), to(to), cost(cost){}
    Edge(int to, ll cost): from(-1), to(to), cost(cost){}
    Edge(int to): from(-1), to(to), cost(1){}

    bool operator<(const Edge& e){
        vec6<int> a(3, vec5<int>(2, vec4<int>(2, vec3<int>(4, vec2<int>(3, vector<int>(5, 0))))));
        return this->cost < e.cost;
    }
    bool operator>(const Edge& e){
        return this->cost > e.cost;
    }
};
vector<ll> dijkstra(vector<vector<int>>& graph, int st){
    priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> que;
    ll INF = 1<<63;
    vector<ll> dist(graph.size(), INF);
    que.push(pair{0, st});
    dist[st] = 0;
    while(!que.empty()){
        auto p = que.top();que.pop();
        ll cost = p.first;
        int point = p.second;
        if(dist[point] < cost)continue;
        for(const Edge& e: graph[point]){
            ll newcost = cost + e.cost;

            if(dist[e.to] > newcost){
                dist[e.to] = newcost;
                que.push(pair{newcost, e.to});
            }
        }
    }
    return dist;
}
const int WALL = 0;
const int ROAD = 1;

int main(){
    int H,W;cin>>H>>W;
    int Ch, Cw;cin>>Ch>>Cw;Ch--;Cw--;
    int Dh, Dw;cin>>Dh>>Dw;Dh--;Dw--;
    vector<vector<ll>> grid(H, vector<ll>(W,ROAD));
    for(int i = 0;i < H;i++){
        string s;cin>>s;
        for(int j = 0;j < W;j++){
            if(s[j] == '.'){
                grid[i][j] = ROAD;
            }else{
                grid[i][j] = WALL;
            }
        }
    }
    queue<tuple<ll, int,int>> q0;
    queue<tuple<ll, int,int>> q1;
    vector<vector<bool>> done(H, vector<bool>(W, false));
    q0.push(make_tuple(0, Ch, Cw));
    while(q0.size() > 0 || q1.size() > 0){
        tuple<ll,int,int> tpl;
        if(q0.empty()){
            tpl = q1.front();q1.pop();
        }else{
            tpl = q0.front();q0.pop();
        }
        ll cost = get<0>(tpl);
        int ph = get<1>(tpl);
        int pw = get<2>(tpl);
        if(done[ph][pw])continue;
        if(ph == Dh && pw == Dw){
            cout<<cost<<endl;
            return 0;
        }
        done[ph][pw] = true;
        for(int i = -2;i <= 2;i++){
            for(int j = -2;j <= 2;j++){
                ll newcost = cost + 1;
                if(abs(i)+abs(j) <= 1)newcost--;
                int newh = ph + i;
                int neww = pw + j;
                if(neww >= W || neww < 0 || newh >= H || newh < 0)continue;
                if(done[newh][neww])continue;
                if(grid[newh][neww] == WALL)continue;
                if(cost != newcost){
                    q1.push(make_tuple(newcost, newh, neww));
                }else{
                    q0.push(make_tuple(newcost, newh, neww));
                }

            }
        }
    }
    cout<<-1<<endl;
}


Measured memory_bytes: 12512