#include <iostream>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <unordered_set>
#include <string>
#include <random>
#include <queue>


using namespace std;

// ans = a ? b : c; // to simplify: if (a) ans = b; else ans = c;
// ans += val; // to simplify: ans = ans + val; and its variants
// index = (index + 1) % n; // index++; if (index >= n) index = 0;
// index = (index + n - 1) % n; // index--; if (index < 0) index = n - 1;
// int ans = (int)((double)d + 0.5); // for rounding to nearest integer
// ans = min(ans, new_computation); // min/max shortcut
// alternative form but not used in this book: ans <?= new_computation;
// some code use short circuit && (AND) and || (OR)

typedef long long ll; // comments that are mixed in with code
typedef pair<int, int> ii; // are aligned to the right like this
typedef vector<ii> vii;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vll;
#define INF 1000000000
#define M_PI 3.14159265358979323846

void printVector2d(vector<vector<int>> a){
    for(int i=0;i<a.size();i++){
        for(int j=0;j<a[i].size();j++){
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<"end"<<endl;
}

void printVector(vector<ll> a){
    for(int i=0;i<a.size();i++){
        cout<<"Total "<<i<<": "<<a[i]<<endl;
    }
}

void printVectorPair(vector<pair<int,int>> a){
    for(int i=0;i<a.size();i++){
        cout<<"Total "<<i<<": "<<a[i].first<<" "<<a[i].second<<endl;
    }
}

void printMap(map<char, int> mp){
    for(auto x:mp){
        cout<<x.first<<": "<<x.second<<endl;
    }
}

void printMapVec(map<int, vector<int>> mpV){
    for(auto x:mpV){
        cout<<x.first<<": ";
        for(auto y:x.second){
            cout<<y<<" ";
        }
        cout<<endl;
    }
}

void printQueue(queue<char> q){
    while(!q.empty()){
        cout<<q.front()<<" ";
        q.pop();
    }
    cout<<" ##### ";
}

int Ch,Cw,Dh,Dw;
bool found_start = false;
int tot_ans = -1;
vector<string> grid;
queue<pair<pair<int,int>,int>> q; // Stores <hi,wi>, dist_ans
vector<vector<bool>> visited;

bool is_valid_node(pair<int,int> node){
    if(node.first<0||node.first>=grid.size()||node.second<0||node.second>=grid[0].size()){
        return false;
    }else if(grid[node.first][node.second]=='#'){
        return false;
    }else if(visited[node.first][node.second]){
        return false;
    }else{
        return true;
    }
}

bool is_node_start_node(pair<int,int> node, int curr_dist_ans) {
    //cout<<"Here: "<<node.first<<" "<<node.second<<endl;
    if (node.first == Ch - 1 && node.second == Cw - 1){
        found_start = true;
        tot_ans = curr_dist_ans;
        return true;
    }else
        return false;
}

void bfs(pair<int,int> node_coord, int curr_dist_ans){
    // Visit curr_node
    visited[node_coord.first][node_coord.second] = true;

    queue<pair<int,int>> bfs_q;
    bfs_q.push(node_coord);
    while(!bfs_q.empty()){
        pair<int,int> curr_node = bfs_q.front();
        bfs_q.pop();

        //Visit other possible nodes and see if they are Ch-1, Cw-1
        pair<int,int> up = {curr_node.first-1,curr_node.second};
        pair<int,int> down = {curr_node.first+1,curr_node.second};
        pair<int,int> left = {curr_node.first,curr_node.second-1};
        pair<int,int> right = {curr_node.first,curr_node.second+1};
        if(is_valid_node(up)){
            bfs_q.push(up);
            visited[up.first][up.second] = true;
//            cout<<"Up: "<<up.first<<" "<<up.second<<endl;
            q.push({up,curr_dist_ans});
            is_node_start_node(up, curr_dist_ans);
        }
        if(is_valid_node(down)){
            bfs_q.push(down);
            visited[down.first][down.second] = true;
//            cout<<"down: "<<down.first<<" "<<down.second<<endl;
            q.push({down,curr_dist_ans});
            is_node_start_node(down, curr_dist_ans);
        }
        if(is_valid_node(left)){
            bfs_q.push(left);
            visited[left.first][left.second] = true;
//            cout<<"left: "<<left.first<<" "<<left.second<<endl;
            q.push({left,curr_dist_ans});
            is_node_start_node(left, curr_dist_ans);
        }
        if(is_valid_node(right)){
            bfs_q.push(right);
            visited[right.first][right.second] = true;
//            cout<<"right: "<<right.first<<" "<<right.second<<endl;
            q.push({right,curr_dist_ans});
            is_node_start_node(right, curr_dist_ans);
        }
    }
}

void magic_search(pair<int,int> node, int curr_dist_ans){
    //search each node in 5x5 grid
    for(int i = node.first-2;i<=node.first+2;i++){
        for(int j = node.second-2;j<=node.second+2;j++){
            // see if node is valid
            if(is_valid_node({i,j})){
                visited[i][j] = true;
                q.push({{i,j},curr_dist_ans});
                is_node_start_node({i,j}, curr_dist_ans);
            }
        }
    }
}

void solve(){
    int H,W;
    string line;
    cin>>H>>W>>Ch>>Cw>>Dh>>Dw;

    vector<vector<bool>> visited_tmp(H,vector<bool>(W,false));
    visited = visited_tmp;
    visited_tmp.clear();

    for(int i=0;i<H;i++){
        cin>>line;
        grid.push_back(line);
    }

    q.push({{Dh-1,Dw-1},0}); // push end node with dist_ans = 0

    int dist_fully_bfsed = -1;

    while(!found_start&&!q.empty()){
        pair<pair<int,int>,int> curr_block = q.front();
//        cout<<curr_block.first.first<<", "<<curr_block.first.second<<" = "<<curr_block.second<<endl;

        queue<pair<pair<int,int>,int>> magic_q;
        if(curr_block.second>dist_fully_bfsed){
            dist_fully_bfsed++;
            //pull all off queue, and add to new queue
            bool reached_next_dist = false;
            while(!reached_next_dist&&!q.empty()){
                pair<pair<int,int>,int> curr_blockk = q.front();
                if(curr_blockk.second>dist_fully_bfsed){
                    reached_next_dist = true;
                    break;
                }
                // Do bfs search from this node
                bfs(curr_blockk.first, curr_blockk.second);
                q.pop();
                magic_q.push(curr_blockk);
            }
        }

        while (!magic_q.empty()) {
            pair<pair<int,int>,int> curr_blockk = magic_q.front();
            // Do magic search from this node with dist_ans +1
            magic_search(curr_blockk.first, curr_blockk.second + 1);
            magic_q.pop();
        }
        //cout<<"HERE!: "<<c<<endl;
    }
//    cout<<"HERE2!"<<endl;
    cout<<tot_ans<<endl;
}

int main() {
    //solve();
    int T;
//    cin >> T;
    T=1;
    for (int case_num = 1; case_num <= T; case_num++) {
        solve();
    }
    return 0;
}

Measured memory_bytes: 4508