#include <bits/stdc++.h>
using namespace std;

// TYPEDEF
// ----------------------------------------
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> Pair;
typedef vector<ll> vll;
typedef vector<vector<ll>> Graph;
typedef vector<string> vs;
typedef vector<pair<ll, ll>> Pll;
typedef queue<ll> qll;

// REPEAT
// ----------------------------------------
#define REP(i,n) for(ll i=0;i<(ll)(n);i++)
#define REPD(i,n) for(ll i=n-1;i>=0;i--)
#define REPA(i,a) for(ll i=0;i<(ll)(a.size());i++);
#define FOR(i,a,b) for(ll i=a;i<=(ll)(b);i++)
#define FORD(i,a,b) for(ll i=a;i>=(ll)(b);i--)
#define COUT(a) cout << (a) << endl;
#define ENDL(a) cout << endl;
#define COUTA(i,a) for(ll i=0;i<(ll)(a.size());i++) {cout << (a)[i] << " ";} cout << endl;

// UTIL
// ----------------------------------------
#define pb push_back
#define paired make_pair
#define ALL(a) (a).begin(),(a).end()
#define SORT(a) sort((a).begin(),(a).end())
#define RSORT(a) sort((a).rbegin(), (a).rend())

ll tousa_no_wa(ld a, ll n, ld d) {
  return (ld(n) / 2) * (2 * a + (n - 1) * d);
}

// PRINT
// ----------------------------------------
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;
#define Yes cout << "Yes" << endl;
#define No cout << "No" << endl;

// DEBUG
// ----------------------------------------
#ifdef _DEBUG
#define debug(x) cout << "[debug] " << #x << ": " << x << endl
#else
#define debug(x)
#endif

template <typename T>
void debugV(const vector<T> v) {
#ifdef _DEBUG
  rep(i, v.size()) {
    cout << i << ":" << v[i] << " ";
  }
  cout << endl;
#else
  (void)v;
#endif
}

// BIT FLAG
// ----------------------------------------
const unsigned int BIT_FLAG_0 = (1 << 0); // 0000 0000 0000 0001
const unsigned int BIT_FLAG_1 = (1 << 1); // 0000 0000 0000 0010
const unsigned int BIT_FLAG_2 = (1 << 2); // 0000 0000 0000 0100
const unsigned int BIT_FLAG_3 = (1 << 3); // 0000 0000 0000 1000
const unsigned int BIT_FLAG_4 = (1 << 4); // 0000 0000 0001 0000
const unsigned int BIT_FLAG_5 = (1 << 5); // 0000 0000 0010 0000
const unsigned int BIT_FLAG_6 = (1 << 6); // 0000 0000 0100 0000
const unsigned int BIT_FLAG_7 = (1 << 7); // 0000 0000 1000 0000
const unsigned int BIT_FLAG_8 = (1 << 8); // 0000 0001 0000 0000
const unsigned int BIT_FLAG_9 = (1 << 9); // 0000 0010 0000 0000
const unsigned int BIT_FLAG_10 = (1 << 10); // 0000 0100 0000 0000
const unsigned int BIT_FLAG_11 = (1 << 11); // 0000 1000 0000 0000

// CONST
// ----------------------------------------
constexpr ll INF = 0x3f3f3f3f3f3f3f3f;
constexpr double PI=3.14159265358979323846; // or M_PI
constexpr int MOD = 1000000007;


struct UnionFind {
  vll data;
 
  UnionFind(ll sz) {
    data.assign(sz, -1);
  }
 
  bool unite(ll x, ll y) {
    x = find(x);
    y = find(y);
    if (x == y) {
      return (false);
    }
    if (data[x] > data[y]) {
      swap(x, y);
    }
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
 
  ll find(ll k) {
    if(data[k] < 0) {
      return (k);
    }
    return (data[k] = find(data[k]));
  }
 
  ll size(ll k) {
    return (-data[find(k)]);
  }

  ll same(ll x, ll y) {
    return (find(x) == find(y));
  }
};

// modint: mod 計算を int を扱うように扱える構造体
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) v += MOD;
    }
    constexpr int getmod() { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        return is >> x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

// 二項係数ライブラリ
template<class T> struct BiCoef {
    vector<T> fact_, inv_, finv_;
    constexpr BiCoef() {}
    constexpr BiCoef(int n) noexcept : fact_(n, 1), inv_(n, 1), finv_(n, 1) {
        init(n);
    }
    constexpr void init(int n) noexcept {
        fact_.assign(n, 1), inv_.assign(n, 1), finv_.assign(n, 1);
        int MOD = fact_[0].getmod();
        for(int i = 2; i < n; i++){
            fact_[i] = fact_[i-1] * i;
            inv_[i] = -inv_[MOD%i] * (MOD/i);
            finv_[i] = finv_[i-1] * inv_[i];
        }
    }
    constexpr T com(int n, int k) const noexcept {
        if (n < k || n < 0 || k < 0) return 0;
        return fact_[n] * finv_[k] * finv_[n-k];
    }
    constexpr T fact(int n) const noexcept {
        if (n < 0) return 0;
        return fact_[n];
    }
    constexpr T inv(int n) const noexcept {
        if (n < 0) return 0;
        return inv_[n];
    }
    constexpr T finv(int n) const noexcept {
        if (n < 0) return 0;
        return finv_[n];
    }
};

// 困ったらここ
// https://ei1333.github.io/luzhiled/


void Main() {
  ll h, w, c_h, c_w, d_h, d_w;
  cin >> h >> w >> c_h >> c_w >> d_h >> d_w;
  vector<vector<char>> s(h, vector<char>(w));
  vector<vector<ll>> check(h, vector<ll>(w, -1));
  REP(i, h) {
    REP(j, w) {
      cin >> s[i][j];
    }
  }

  queue<Pair> q;
  ll group = 0;
  ll group_num = 0;

  REP(i, h) {
    REP(j, w) {
      if (check[i][j] != -1) {
        continue;
      }
      else if (s[i][j] == '#') {
        continue;
      }
      q.emplace(i, j);
      check[i][j] = group;
      group_num = max(group_num, group);
      while(!q.empty()) {
        ll x = q.front().first; //tate
        ll y = q.front().second; //yoko
        q.pop();
        if (s[x][y] == '.') {
          // hidari
          if (y > 0 and check[x][y - 1] == -1 and s[x][y - 1] != '#') {
            q.emplace(x, y - 1);
            check[x][y - 1] = group;
            group_num = max(group_num, group);
          }
          // migi
          if (y < (w - 1) and check[x][y + 1] == -1 and s[x][y + 1] != '#') {
            q.emplace(x, y + 1);
            check[x][y + 1] = group;
            group_num = max(group_num, group);
          }
          // ue
          if (x > 0 and check[x - 1][y] == -1 and s[x - 1][y] != '#') {
            q.emplace(x - 1, y);
            check[x - 1][y] = group;
            group_num = max(group_num, group);
          }
          // shita
          if (x < (h - 1) and check[x + 1][y] == -1 and s[x + 1][y] != '#') {
            q.emplace(x + 1, y);
            check[x + 1][y] = group;
            group_num = max(group_num, group);
          }
        }
      }
      group++;
    }
  }

  Graph g(group_num + 1);
  
  UnionFind uf(group_num + 1);
  REP(i, h) {
    REP(j, w) {
      FOR(diff_i, -2, 2) {
        FOR(diff_j, -2, 2) {
          if ((0 <= i + diff_i) and (i + diff_i < h) and (0 <= j + diff_j) and (j + diff_j < w)) {
            if (check[i][j] != -1 and check[i + diff_i][j + diff_j] != -1) {
              uf.unite(check[i][j], check[i + diff_i][j + diff_j]);
              if (check[i][j] != check[i + diff_i][j + diff_j]) {
                g[check[i][j]].push_back(check[i + diff_i][j + diff_j]);
                g[check[i + diff_i][j + diff_j]].push_back(check[i][j]);
              }
            }
          }
        }
      }
    }
  }

  REP(i, group_num + 1) {
    SORT(g[i]);
    g[i].erase(unique(g[i].begin(), g[i].end()), g[i].end());
    // COUTA(l, g[i]);
  }

  ll start_group = check[c_h - 1][c_w - 1];
  ll goal_group = check[d_h - 1][d_w - 1];

  if (uf.find(start_group) != uf.find(goal_group)) {
    COUT(-1);
  }
  else {
    vll toutatsu(group_num + 1, -1);
    queue<ll> ans;
    ans.push(start_group);
    toutatsu[start_group] = 0;
    while(!ans.empty()) {
      ll target = ans.front();
      ans.pop();
      REP(o, g[target].size()) {
        if (toutatsu[g[target][o]] == -1) {
          toutatsu[g[target][o]] = toutatsu[target] + 1;
          ans.push(g[target][o]);
        }
      }
    }
    COUT(toutatsu[goal_group]);
    cerr << "aaaa" << endl;
  }

/*
  REP(i, group + 1) {
    COUT(uf.find(i));
  }
  */
  
}

int main()
{
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cout << fixed << setprecision(15);
	Main();
}

/*
5
24 11 8 3 16
*/


Measured memory_bytes: 57432