#include <iostream>
#include <fstream>
#include <algorithm>
#include <iomanip>
#include <random>
#include <ctime>
#include <bitset>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#include <cstring>
#include <queue>
#include <deque>
#include <stack>
#include <climits>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define ld long double
#define ull unsigned long long
#define ll long long
#define pb push_back
#define pii pair<int, int>
#define pll pair<ll, ll>
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define fast_io cout.tie(0), cin.tie(0), ios_base::sync_with_stdio(0)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using namespace std;
//using namespace __gnu_pbds;
//typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
ld eps = (ld)1 / 1e9;
ll inf = LLONG_MAX, mod1 = 1e9 + 7, mod2 = 998244353;
ll sqr(ll a) { return a * a; }
ll qb(ll a) { return a * a * a; }
ll gcd(ll a, ll b) { return !a ? b : gcd(b % a, a); }
ll binpow(ll a, ll b, ll mod) { return b ? (b % 2 ? (a * (sqr(binpow(a, b / 2, mod)) % mod)) % mod : sqr(binpow(a, b / 2, mod)) % mod) : 1; }
ll binmult(ll a, ll b, ll mod) { return b ? (b % 2 ? (2 * binmult(a, b / 2, mod) + a) % mod : (2 * binmult(a, b / 2, mod)) % mod) : 0; }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool bl[1002][1002], used[1002][1002];
int nm[1002][1002];
char ch;

int main()
{
    fast_io;
    ll t, H, W, i, j, cx, cy, dx, dy;
    cin >> H >> W >> cx >> cy >> dx >> dy;
    for (i = 1; i <= H; i++)
        for (j = 1; j <= W; j++)
            cin >> ch, bl[i][j] = (ch == '#');
    queue<pii> q;
    set<pii> st;
    q.push({cx, cy});
    used[cx][cy] = 1;
    while (!q.empty())
    {
        st.clear();
        while (!q.empty())
        {
            cx = q.front().first;
            cy = q.front().second;
            q.pop();
            used[cx][cy] = 1;
            t = nm[cx][cy];
            st.insert({cx, cy});
            if (cx > 1 && !used[cx - 1][cy] && !bl[cx - 1][cy]) used[cx - 1][cy] = 1, q.push({cx - 1, cy}), nm[cx - 1][cy] = t;
            if (cy > 1 && !used[cx][cy - 1] && !bl[cx][cy - 1]) used[cx][cy - 1] = 1, q.push({cx, cy - 1}), nm[cx][cy - 1] = t;
            if (cx < H && !used[cx + 1][cy] && !bl[cx + 1][cy]) used[cx + 1][cy] = 1, q.push({cx + 1, cy}), nm[cx + 1][cy] = t;
            if (cy < W && !used[cx][cy + 1] && !bl[cx][cy + 1]) used[cx][cy + 1] = 1, q.push({cx, cy + 1}), nm[cx][cy + 1] = t;
        }
        for (auto f: st)
        {
            cx = f.first;
            cy = f.second;
            used[cx][cy] = 1;
            for (i = cx - 2; i <= cx + 2; i++)
            {
                for (j = cy - 2; j <= cy + 2; j++)
                {
                    if (used[i][j] || i < 1 || j < 1 || i > H || j > W || bl[i][j]) continue;
                    q.push({i, j});
                    used[i][j] = 1;
                    nm[i][j] = t + 1;
                }
            }
        }
    }
    cout << (used[dx][dy] ? nm[dx][dy] : -1);
    return 0;
}

Measured memory_bytes: 10000