#include using namespace std; using ll = long long; const int iinf = 1e9; const ll inf = 1e18; template struct Mint { using M=Mint; ll v; M& put(ll x) { v=(x>=1; } return res; } M inv() { return pow(mod-2); } }; template ostream&operator<<(ostream&o,Mintv){return o< ostream& operator<<(ostream &o, vector v) { for (int i = 0; i < v.size(); i++) o << v[i] << (i+1 struct SegTree { using F = function; int n; F f; T ti; vector dat; SegTree() {} SegTree(F f, T ti,int num) : f(f), ti(ti) { n = max(__bit_ceil(num), 1); dat.assign(n << 1, ti); } SegTree(F f,T ti,vector&v):SegTree(f,ti,v.size()){ for (int i = 0; i < v.size(); i++) dat[n + i] = v[i]; for(int i=n-1;i;i--) dat[i]=f(dat[i*2], dat[i*2+1]); } void set_val(int k, T x) { dat[k += n] = x; while(k >>= 1) dat[k] = f(dat[k*2], dat[k*2+1]); } T query(int a, int b) { if (a >= b) return ti; T vl = ti, vr = ti; for (int l=a+n, r=b+n; l>=1, r>>=1) { if (l & 1) vl = f(vl, dat[l++]); if (r & 1) vr = f(dat[--r], vr); } return f(vl, vr); } }; struct Edge { int to; ll cost; }; const int MOD = 998244353; // a^e mod ll modpow(ll a, ll e=MOD-2){ ll r=1; while(e){ if(e&1) r=r*a%MOD; a=a*a%MOD; e>>=1; } return r; } using mint = Mint; using i128 = __int128_t; using ull = unsigned long long; i128 pow128(i128 a,ull d,ull m){//remove m,i128->mint64 i128 res=1; while (d) { if (d&1) (res*=a)%=m; (a*=a)%=m; d>>=1; } return res; } bool is_prime(ull n) { if (n <= 1 || (n > 2 && n % 2 == 0)) return false; // mint64::set_mod(n); // {2,7,61,-1} -> n < 4759123141 (= 2^32) int test[] = {2,3,5,7,11,13,17,19,23,-1}; // n<1e16 ull d = n - 1, s = 0; while (d % 2 == 0) ++s, d /= 2; for (int i = 0; test[i] < n && test[i] != -1; i++) { auto x = pow128(test[i], d, n); if (x == 1) goto end; for (int r = 0; r < s; r++) { if (x == n - 1) goto end; (x *= x) %= n; } return false; end:; } return true; } int main() { cin.tie(0)->sync_with_stdio(false); int H, W; cin >> H >> W; int sx, sy, gx, gy; cin >> sx >> sy >> gx >> gy; // 1-indexed -> 0-index sx--; sy--; gx--; gy--; vector grid(H); for (int i = 0; i < H; i++) { cin >> grid[i]; } int maxMoves = H * W; vector dist(H, vector(W, vector(maxMoves+1, iinf))); struct State { int x, y, h; }; queue q; dist[sx][sy][0] = 0; q.push({sx, sy, 0}); int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1}; while (!q.empty()) { State cur = q.front(); q.pop(); int x = cur.x, y = cur.y, h = cur.h; int d = dist[x][y][h]; for (int k = 0; k < 4; k++) { int nx = x + dx[k], ny = y + dy[k]; if (nx < 0 || nx >= H || ny < 0 || ny >= W) continue; if (grid[nx][ny] == '#') continue; int nh = h + (k >= 2); int nd = d + 1; int nv = nd - nh; if (nv > maxMoves || nh > maxMoves) continue; if (nd < dist[nx][ny][nh]) { dist[nx][ny][nh] = nd; q.push({nx, ny, nh}); } } } int dv = abs(sx - gx); int dh = abs(sy - gy); int ans = iinf; vector oksv; vector oksh; if (dv % 2 == 1) { if (is_prime(2+dv)) oksv.push_back(2); } else { if (dv == 0) oksh.push_back(2); for (int i = 3; ; i += 2) { if (is_prime(i) and is_prime(i+dv)) { oksv.push_back(i); if (i > maxMoves) break; } } } if (dh % 2 == 1) { if (is_prime(2+dh)) oksh.push_back(2); } else { if (dh == 0) oksh.push_back(2); for (int i = 3; ; i += 2) { if (is_prime(i) and is_prime(i+dh)) { oksh.push_back(i); if (i > maxMoves) break; } } } for (int i = 1; i <= maxMoves; i++) { if (dist[gx][gy][i] >= iinf) continue; int j = dist[gx][gy][i]-i; int mv = (i-dv)/2; int mh = (j-dh)/2; auto itv = lower_bound(oksv.begin(), oksv.end(), mv); auto ith = lower_bound(oksh.begin(), oksh.end(), mh); if (itv != oksv.end() && ith != oksh.end()) { mv = *itv; mh = *ith; // cout << mv << " " << mh << endl; ans = min(ans, mv + mv+dv + mh + mh+dh); } } cout << (ans==iinf?-1:ans) << endl; return 0; }