#include <cmath>
#include <cstdlib>
#include <iostream>
#include <bitset>
#include <deque>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <chrono>
#include <random>
#include <tuple>
#include <utility>
#include <fstream>
#include <complex>
#include <cstdint>
#define _USE_CMATH_DEFINES

typedef std::pair<long, long> P;

const long INF = (1l << 30);
const long LINF = (1l << 60); //1.15*10^18

long di[] = {-1, 0, 0, 1};
long dj[] = {0, -1, 1, 0};

//0_indexed

class union_find{
private:
    std::vector<long> parent;
    std::vector<long> rank;
    std::vector<long> m_size;

public:
    union_find(long n);
    long root(long x);
public:
    bool same(long x, long y);
    void unite(long x, long y);
    long size(long x);
};

union_find::union_find(long n){
    parent = std::vector<long>(n);
    rank = std::vector<long>(n, 0);
    m_size = std::vector<long>(n, 1);
    for(long i = 0; i < n; i++){
        parent[i] = i;
    }
}
long union_find::root(long x){
    if(x < 0 || parent.size() <= x){
        printf("union_find::root range invalid!\n");
        return -1;
    }
    if(parent[x] == x){
        return x;
    }else{
        long res = root(parent[x]);
        parent[x] = res;
        return res;
    }
}
bool union_find::same(long x, long y){
    return root(x) == root(y);
}
void union_find::unite(long x, long y){
    x = root(x);
    y = root(y);
    if(x == y){
        return;
    }
    if(rank[x] < rank[y]){
        parent[x] = y;
        m_size[y] += m_size[x];
    }else{
        parent[y] = x;
        m_size[x] += m_size[y];
        if(rank[x] == rank[y]){
            rank[x]++;
        }
    }
}
long union_find::size(long x){
    return m_size[root(x)];
}

bool range_valid(long h, long w, long visi, long visj){
    return (0 <= visi && visi < h && 0 <= visj && visj < w);
}

long solve(long h, long w, long ch, long cw, long dh, long dw, std::vector<std::string> field){
    union_find uf(h*w);
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            if(field[i][j] == '#') continue;
            for(int k = 0; k < 4; k++){
                long ni = i+di[k];
                long nj = j+dj[k];
                if(range_valid(h, w, ni, nj) && field[ni][nj] == '.'){
                    uf.unite(i*w+j, ni*w+nj);
                }
            }
        }
    }
    std::map<long, long> root_id; //root_id[root] = id
    for(long i = 0; i < h; i++){
        for(long j = 0; j < w; j++){
            long rt = uf.root(i*w+j);
            if(field[i][j] == '.' && root_id.count(rt) == 0){
                root_id[rt] = root_id.size();
            }
        }
    }

    /*
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            if(field[i][j] == '#'){
                printf(" # ");
            }else{
                printf("%2ld ", root_id[uf.root(i*w+j)]);
            }
        }
        printf("\n");
    }
    //*/

    std::vector<std::vector<long> > edge(root_id.size());
    std::set<P> edge_memo;
    for(long i = 0; i < h; i++){
        for(long j = 0; j < w; j++){
            if(field[i][j] == '#') continue;
            for(long k = -2; k <= 2; k++){
                for(long l = -2; l <= 2; l++){
                    long ni = i+k;
                    long nj = j+l;
                    if(range_valid(h, w, ni, nj) && field[ni][nj] == '.'){
                        long id = root_id[uf.root(i*w+j)], nid = root_id[uf.root(ni*w+nj)];
                        if(id != nid && edge_memo.count(P(id, nid)) == 0){
                            edge[id].push_back(nid);
                            edge[nid].push_back(id);
                            edge_memo.insert(P(id, nid));
                            edge_memo.insert(P(nid, id));
                        }
                    }
                }
            }
        }
    }

    /*
    for(long i = 0; i < edge.size(); i++){
        printf("%ld : ", i);
        for(long j = 0; j < edge[i].size(); j++){
            printf("%ld ", edge[i][j]);
        }
        printf("\n");
    }
    //*/

    long st = root_id[uf.root(ch*w+cw)];
    long gl = root_id[uf.root(dh*w+dw)];

    std::vector<long> dist(root_id.size(), -1);
    dist[st] = 0;
    std::queue<long> que;
    que.push(st);
    while(!que.empty()){
        long vis = que.front();
        que.pop();
        for(int i = 0; i < edge[vis].size(); i++){
            long nx = edge[vis][i];
            if(dist[nx] == -1){
                dist[nx] = dist[vis] + 1;
                que.push(nx);
            }
        }
    }
    /*
    for(auto it = root_id.begin(); it != root_id.end(); it++){
        printf("%ld %ld\n", it->first, it->second);
    }
    //*/
    return dist[gl];
}

int main(){
    long h, w;
    scanf("%ld%ld", &h, &w);
    std::vector<std::string> field(h);
    long ch, cw, dh, dw;
    scanf("%ld%ld%ld%ld", &ch, &cw, &dh, &dw);
    ch--;
    cw--;
    dh--;
    dw--;
    for(int i = 0; i < h; i++){
        std::cin >> field[i];
    }
    /*
    for(int i = 0; i < h; i++){
        std::cout << field[i] << std::endl;
    }
    //*/
    printf("%ld\n", solve(h, w, ch, cw, dh, dw, field));
}


Measured memory_bytes: 71604