#include <bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < (ll)(n); ++i)
#define rep2(i, s, n) for (ll i = s; i < (ll)(n); i++)
#define repr(i, n) for (ll i = n; i >= 0; i--)
#define pb push_back
#define COUT(x) cout << (x) << "\n"
#define COUTF(x) cout << setprecision(15) << (x) << "\n"
#define ENDL cout << "\n"
#define DF(x) x.erase(x.begin())
#define ALL(x) x.begin(), x.end()
#define SORT(x) sort(ALL(x))
#define REVERSE(x) reverse(ALL(x))
#define MAX(x) *max_element(ALL(x))
#define MAXI(x) max_element(ALL(x)) - x.begin()
#define SUM(x) accumulate(ALL(x), 0)
#define COUNT(x, y) count(ALL(x), y);
#define ANS cout << ans << "\n"
#define init() \
  cin.tie(0);  \
  ios::sync_with_stdio(false)
#define LINE cerr << "[debug] line: " << __LINE__ << "\n";
#define debug(x) cerr << "[debug] " << #x << ": " << x << "\n";
#define debugV(v)                       \
  cerr << "[debugV] " << #v << ":";     \
  rep(z, v.size()) cerr << " " << v[z]; \
  cerr << "\n";
using namespace std;
using ll = long long;
using ld = long double;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using mll = map<ll, ll>;
using qll = queue<ll>;
using P = pair<ll, ll>;
using vp = vector<P>;
using vs = vector<string>;

template <typename T>
inline istream& operator>>(istream& i, vector<T>& v) {
  rep(j, v.size()) i >> v[j];
  return i;
}

template <typename T1, typename T2>
inline istream& operator>>(istream& i, pair<T1, T2>& v) {
  return i >> v.first >> v.second;
}

constexpr ll INF = 0x3f3f3f3f3f3f3f3f;
constexpr ld PI = 3.141592653589793238462643383279;
ll get_digit(ll x) {
  return to_string(x).size();
}

ll gcd(ll x, ll y) {
  return y ? gcd(y, x % y) : x;
}

ll lcm(ll a, ll b) {
  return a / gcd(a, b) * b;
}

template <class T>
bool chmax(T& a, const T& b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}

template <class T>
bool chmin(T& a, const T& b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

vector<P> factorize(ll n) {
  vector<P> result;
  for (ll i = 2; i * i <= n; ++i) {
    if (n % i == 0) {
      result.pb({i, 0});
      while (n % i == 0) {
        n /= i;
        result.back().second++;
      }
    }
  }
  if (n != 1) {
    result.pb({n, 1});
  }
  return result;
}

vll divisor(ll n) {
  vll ret;
  for (ll i = 1; i * i <= n; i++) {
    if (n % i == 0) {
      ret.push_back(i);
      if (i * i != n) ret.push_back(n / i);
    }
  }
  SORT(ret);
  return (ret);
}

const int mod = 1000000007;
struct mint {
  ll x;
  mint(ll x = 0) : x((x % mod + mod) % mod) {
  }
  mint operator-() const {
    return mint(-x);
  }
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod - a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const {
    return mint(*this) += a;
  }
  mint operator-(const mint a) const {
    return mint(*this) -= a;
  }
  mint operator*(const mint a) const {
    return mint(*this) *= a;
  }
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1) a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const {
    return pow(mod - 2);
  }
  mint& operator/=(const mint a) {
    return *this *= a.inv();
  }
  mint operator/(const mint a) const {
    return mint(*this) /= a;
  }
};
istream& operator>>(istream& is, const mint& a) {
  return is >> a.x;
}
ostream& operator<<(ostream& os, const mint& a) {
  return os << a.x;
}

struct combination {
  vector<mint> fact, ifact;
  combination(ll n) : fact(n + 1), ifact(n + 1) {
    assert(n < mod);
    fact[0] = 1;
    for (ll i = 1; i <= n; ++i) {
      fact[i] = fact[i - 1] * i;
    }
    ifact[n] = fact[n].inv();
    for (ll i = n; i >= 1; --i) {
      ifact[i - 1] = ifact[i] * i;
    }
  }
  mint operator()(ll n, ll k) {
    if (k < 0 || k > n) return 0;
    return fact[n] * ifact[k] * ifact[n - k];
  }
};

struct A {
  ll x;
  ll y;
  ll kaisu;
};

signed main() {
  init();
  ll H, W, Sh, Sw, Gh, Gw;
  cin >> H >> W >> Sh >> Sw >> Gh >> Gw;
  Sh--;
  Sw--;
  Gh--;
  Gw--;
  vs S(H);
  cin >> S;

  vvll d(H, vll(W, -1));

  // stack<A> s;
  deque<A> s;
  s.push_front({Sh, Sw, 0});
  // s.push({Sh, Sw, 0});

  while (!s.empty()) {
    A t = s.front();
    s.pop_front();

    // A t = s.top();
    // s.pop();

    if (t.x < 0 or t.y < 0 or t.x >= H or t.y >= W or S[t.x][t.y] == '#')
      continue;

    if (d[t.x][t.y] == -1 or t.kaisu < d[t.x][t.y]) {
      d[t.x][t.y] = t.kaisu;

      // ll left = 0;
      // if (t.y != 0 and S[t.x][t.y - 1] == '#') left = -2;

      // ll top = 0;
      // if (t.x != 0 and S[t.x - 1][t.y] == '#') top = -2;

      // ll right = 0;
      // if (t.y != W - 1 and S[t.x][t.y + 1] == '#') right = 3;

      // ll bottom = 0;
      // if (t.x != H - 1 and S[t.x + 1][t.y] == '#') bottom = 3;

      // rep2(i, top, bottom) {
      //   rep2(j, left, right) {
      rep2(i, -2, 3) {
        rep2(j, -2, 3) {
          ll nx = t.x + i;
          ll ny = t.y + j;
          if (nx < 0 or ny < 0 or nx >= H or ny >= W or S[nx][ny] == '#')
            continue;
          // s.push({nx, ny, t.kaisu + 1});
          s.push_back({nx, ny, t.kaisu + 1});
        }
      }

      // if (t.x != 0) s.push({t.x - 1, t.y, t.kaisu});
      // if (t.y != 0) s.push({t.x, t.y - 1, t.kaisu});
      // if (t.x != H - 1) s.push({t.x + 1, t.y, t.kaisu});
      // if (t.y != W - 1) s.push({t.x, t.y + 1, t.kaisu});

      if (t.x != 0) s.push_front({t.x - 1, t.y, t.kaisu});
      if (t.y != 0) s.push_front({t.x, t.y - 1, t.kaisu});
      if (t.x != H - 1) s.push_front({t.x + 1, t.y, t.kaisu});
      if (t.y != W - 1) s.push_front({t.x, t.y + 1, t.kaisu});
    }
  }

  // rep(i, H) {
  //   rep(j, W) {
  //     cout << d[i][j] << " ";
  //   }
  //   ENDL;
  // }

  // debug(Gh);
  // debug(Gw);
  // debug(d[3][3]);

  ll ans = d[Gh][Gw];
  ANS;

  return 0;
}

Measured memory_bytes: 15740