#ifdef __APPLE__
#include <iostream>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <set>
#include <algorithm>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <iomanip>
#include <cmath>
#include <ctgmath>
#include <math.h>
#include <cassert>
#include <chrono>
#else
#include <bits/stdc++.h>
#endif

using namespace std;
#define io ios_base::sync_with_stdio(false), cin.tie(NULL)
#define GFOR(i,a,n) for (i=a;i<n;i++)
#define FOR(i,a,n) for (int i=a;i<n;i++)
#define RFOR(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define sz(x) ((int)(x).size())
#define tc(t) for (int tc=1; tc<=t; tc++)
typedef vector<int> vi;
typedef vector<string> vs;
typedef vector<long long int> vll;
typedef vector<pair<int, int> > vpi;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll, ll> pll;
mt19937 mrand(random_device{}()); 
const ll mod=1000000007;
int rnd(int x) { return mrand() % x;}
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll modInverse (ll a) {ll p = mod - 2; return powmod(a, p);}
// head
int h, w;
vi dirr = {1, -1, 0, 0};
vi dirc = {0, 0, 1, -1};
int comp = 1;
bool valid(int cr, int cc) {
    return (cr >= 0 and cc >= 0 and cr < h and cc < w);
}
void dfs(int r, int c, vector<string>& grid, vector<vi>& gn) {
    gn[r][c] = comp;
    for (int k = 0; k < 4; k++) {
        int cr, cc;
        cr = r + dirr[k];
        cc = c + dirc[k];
        if (!valid(cr, cc))
            continue;
        if (gn[cr][cc] or grid[cr][cc] == '#')
            continue;
        dfs(cr, cc, grid, gn);
    }
}

void solve() {
    cin >> h >> w;
    int sr, sc, dr, dc;
    cin >> sr >> sc >> dr >> dc;
    sr--, sc--, dr--, dc--;
    vector<string> grid(h);
    for (auto &x : grid)
        cin >> x;
    vector<vi> gn(h, vi(w));
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            if (!gn[i][j]) {
                dfs(i, j, grid, gn);
                comp++;
            }
        }
    }

    int src = gn[sr][sc];
    int dest = gn[dr][dc];
    vector<unordered_set<int>> graph(comp);
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            for (int r = i-2; r <= i+2; r++) {
                for (int c = j-2; c <= j+2; c++) {
                    if (valid(r, c) and grid[i][j] == '.' and grid[r][c] == '.' and gn[i][j] != gn[r][c]) {
                        graph[gn[i][j]].insert(gn[r][c]);
                        graph[gn[r][c]].insert(gn[i][j]);
                    }
                }
            }
        }
    }

    queue<pii> q;
    q.push({src, 0});
    vi vis(comp);
    vis[src] = true;
    while (!q.empty()) {
        auto top = q.front();
        q.pop();
        if (top.fi == dest) {
            cout << top.se << "\n";
            return;
        }
        for (auto x: graph[top.fi]) {
            if (!vis[x])
                vis[x] = true, q.push({x, top.se + 1});
        }
    }
    cout << -1 << '\n';
}

int main() {
    #ifdef LOCAL
    auto t1 = std::chrono::high_resolution_clock::now();
    #endif

    io;
    solve();

    #ifdef LOCAL
    auto t2 = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();

    std::cout << "Time Taken: " << duration << "\n";
    #endif

}
// check for edge cases in limits
// printing double may print 1.223232e9 like values, beware of that
// carefully observe simulation of test cases
// multiset erase is does not do what it is supposed to


Measured memory_bytes: 72904