#include<bits/stdc++.h>
#define watch(x) cout << (#x) << " is " << (x) << endl
#define endl "\n"
typedef long long ll;
using namespace std;
int static fast = [](){
  ios::sync_with_stdio(false);
  cin.tie(0); cout.tie(0); return 0;
}();
// freopen("input.txt", "r", stdin);

int main() {
    int h, w;
    cin >> h >> w;
    vector<int> src(2, 0);
    vector<int> dst(2, 0);
    for(auto& val: src) {
        cin >> val;
        val -= 1;
    }
    for(auto& val: dst) {
        cin >> val;
        val -= 1;
    }
    string s;
    vector<vector<int>> grid(h, vector<int>(w, 0));
    for(int i = 0; i < h; i++) {
        cin >> s;
        for(int j = 0; j < w; j++) {
            if (s[j] == '#')
                grid[i][j] = -1;
        }
    }
    
    vector<int> dir = {1, 0, -1, 0, 1};
    auto fill_grid = [&] (int r0, int c0, int color) {
        vector<int> dq = {r0*w + c0};
        grid[r0][c0] = color;
        while(!dq.empty()) {
            vector<int> new_dq;
            for(int node: dq) {
                int r = node / w;
                int c = node % w;
                for(int d = 0; d < 4; d++) {
                    int rr = r + dir[d];
                    int cc = c + dir[d+1];
                    if (rr < 0 || rr >= h || cc < 0 || cc >= w)
                        continue;
                    if (grid[rr][cc] == 0) {
                        grid[rr][cc] = color;
                        new_dq.push_back(rr*w+cc);
                    }
                }
            }
            dq.swap(new_dq);
        }        
    };
    vector<int> blk;
    int label = 1;

    for(int i = 0; i < h; i++) {
        for(int j = 0; j < w; j++) {
            if (grid[i][j] == 0) {
                fill_grid(i, j, label);
                label += 1;
            } else if (grid[i][j] == -1) {
                blk.push_back(i*w+j);
            }
        }
    }
    /*
    for(int i = 0; i < h; i++) {
        for(int j = 0; j < w; j++) {
            if (grid[i][j] == -1)
                cout << 'X';
            else
                cout << grid[i][j];
        }
        cout << endl;
    }*/

    int src_c = grid[src[0]][src[1]];
    int dst_c = grid[dst[0]][dst[1]];
    if (src_c == dst_c) {
        cout << 0 << endl;
        return 0;
    }
    
    unordered_map<int, unordered_set<int>> e;
    for(int i = 0; i < h; i++) {
        for(int j = 0; j < w; j++) {
            if (grid[i][j] != -1) {
                for(int dr : {-2, -1, 0, 1, 2}) {
                    for(int dc: {-2, -1, 0, 1, 2}) {
                        int rr = i + dr;
                        int cc = j + dc;
                        if (rr < 0 || rr >= h || cc < 0 || cc >= w)
                            continue;
                        if (grid[rr][cc] != -1 && grid[rr][cc] != grid[i][j]) {
                            int c1 = grid[rr][cc];
                            int c2 = grid[i][j];
                            e[c1].insert(c2);
                            e[c2].insert(c1);
                        }
                    }
                }                
            }
        }
    }
    /*
    unordered_map<int, unordered_set<int>> e;
    for(int node: blk) {
        int r = node / w;
        int c = node % w;
        // vector<int> used;
        unordered_set<int> used;
        for(int dr : {-1, 0, 1}) {
            for(int dc: {-1, 0, 1}) {
                int rr = r + dr;
                int cc = c + dc;
                if (rr < 0 || rr >= h || cc < 0 || cc >= w)
                    continue;
                if (grid[rr][cc] != -1) {
                    used.insert(grid[rr][cc]);
                }
            }
        }
        vector<int> used2 = vector<int>(used.begin(), used.end());
        for(int c1: used2) {
            for(int c2: used2) {
                if (c1 != c2) {
                    e[c1].insert(c2);
                    e[c2].insert(c1);
                }
            }
        }       
    }
    */
    
    int step = 0;
    vector<int> dq = {src_c};
    unordered_set<int> visit;
    visit.insert(src_c);
    while(!dq.empty()) {
        vector<int> new_dq;
        for(int node: dq) {
            for(int neibor: e[node]) {
                if (visit.count(neibor) == 0) {
                    visit.insert(neibor);                    
                    new_dq.push_back(neibor);
                    // cout << "step " << step+1 << ", add" << neibor << endl;
                    if (neibor == dst_c) {
                        cout << (step+1) << endl;
                        return 0;
                    }
                }
            }
        }
        dq.swap(new_dq);
        step += 1;
    }
    cout << -1 << endl;
    return 0;
}


Measured memory_bytes: 48148