#include <iostream>
#include <string>
#include <vector>
#include <deque>

using namespace std;

/*
5 15
5 9
1 7
.#..#.g#....#..
.#############.
##############.
.###.##...####.
#....#..s..#...

left  = 5
right = 3
 */
int main() {
  // Height, Width, start_y, start_x, goal_y, goal_x
  int H, W, sy, sx, gy, gx;
  cin >> H >> W >> sy >> sx >> gy >> gx;
  sy--; sx--; gy--; gx--;
  
  //bool visited[H][W];
  pair<int, int> start = make_pair(sy, sx);
  pair<int, int> goal  = make_pair(gy, gx);
  vector<vector<char>> maze(H, vector<char>(W));
  for (int i=0; i<H; i++) {
    string line;
    cin >> line;
    for (int j=0; j<W; j++) {
      maze[i][j] = line[j];
      //cout << "maze[i][j]:" << maze[i][j] << "\n";
    }
  }

  deque<pair<int, int>> dq;
  dq.push_back(start);
  //cout << "dq.push_back(start):" << start.first << " " << start.second << "\n";

  // cost to reach y, x. start has cost 0.
  vector<vector<long long>> cost(H, vector<long long>(W, 1e9));
  cost[start.first][start.second] = 0;

  // move within y-2 ~ y+2, x-2 ~ x+2 (25 patterns in total)
  vector<int> dy = {-1,0,1, 0,-2,-2,-2,-2,-2,-1,-1,-1,-1, 0,0,0, 1, 1,1,1, 2, 2,2,2,2};
  vector<int> dx = { 0,1,0,-1,-2,-1, 0, 1, 2,-2,-1, 1, 2,-2,0,2,-2,-1,1,2,-2,-1,0,1,2};

  // starting loop
  while ( !dq.empty() ) {
    int y = dq.front().first;
    int x = dq.front().second;
    dq.pop_front();
    //cout << "checking y:" << y << " x:" << x << "\n";
    /*
    // not yet break ... there might be effective way
    if (y == goal.first && x == goal.second) {
      cout << "break\n";
      break;
    }
    */
    /*
    if ( visited[y][x] ) {
      cout << "visited y:" << y << " x:" << x << " , continue\n";
      continue;
    }
    visited[y][x] = true;
    */

    // move by walk
    for (int i=0; i<4; i++) {
      int new_y = y + dy[i];
      int new_x = x + dx[i];

      //cout << "move by walk. checking new_y:" << new_y << " new_x:" << x << "\n";
      if (new_y < 0 || H-1 < new_y || new_x < 0 || W-1 < new_x || maze[new_y][new_x] == '#') {
        //cout << "cannot move to new_y, new_x. continue\n";
        continue;
      }

      if ( cost[new_y][new_x] > cost[y][x] ) {
        //cout << "push_front new_y:" << new_y << " new_x:" << x << "\n";
        cost[new_y][new_x] = cost[y][x];
        dq.push_front( make_pair(new_y, new_x) );
      }
    }

    // move by charm
    for (int i=4; i<25; i++) {
      int new_y = y + dy[i];
      int new_x = x + dx[i];
      //cout << "move by charm. checking new_y:" << new_y << " new_x:" << x << "\n";
      if (new_y < 0 || H-1 < new_y || new_x < 0 || W-1 < new_x || maze[new_y][new_x] == '#') {
        //cout << "cannot move to new_y, new_x. continue\n";
        continue;
      }

      // currect cost to reach y, x = cost[new_y][new_x]. If we add 1 to cost[y][x] and still lower than current cost, we should consider cost[y][x]+1 as temporary optimal cost.
      if ( cost[new_y][new_x] > cost[y][x] + 1 ) {
        //cout << "push_back new_y:" << new_y << " new_x:" << x << "\n";
        cost[new_y][new_x] = cost[y][x] + 1;
        dq.push_back( make_pair(new_y, new_x) );
      }
    }
  }

  if ( cost[goal.first][goal.second] == 1e9 ) {
    cout << "-1\n";
  }
  else {
    cout << cost[goal.first][goal.second] << "\n";
  }
}


Measured memory_bytes: 12428