//  [rust]
use std::io::{stderr, stdin, stdout, BufReader, BufWriter, Cursor, Read, Write};
use std::iter::Iterator;
use std::str::FromStr;
use std::collections::VecDeque;
// use std::slice::Iter;
// use std::vec::IntoIter;

#[allow(dead_code)]
fn main() {
  let stdin = stdin();
  let r = &mut BufReader::new(stdin.lock());
  let stdout = stdout();
  let w = &mut BufWriter::new(stdout.lock());
  let stderr = stderr();
  let err = &mut BufWriter::new(stderr.lock());
  run(r, w, err);
  w.flush().unwrap();
  err.flush().unwrap();
}

macro_rules! _ft { () => (impl FnOnce(&mut Cursor<Vec<u8>>, &mut Vec<u8>, &mut Vec<u8>)); }

#[allow(dead_code)]
fn test(input: &str, output: &str, f: _ft!()) {
  let r = &mut Cursor::new(input.as_bytes().to_vec());
  let w: &mut Vec<u8> = &mut Vec::new();
  let err: &mut Vec<u8> = &mut Vec::new();
  f(r, w, err);
  let mut stderr = stderr();
  writeln!(stderr, "{}", String::from_utf8(err.to_vec()).unwrap()).unwrap();
  stderr.flush().ok();
  assert_eq!(String::from_utf8(w.to_vec()).unwrap(), output)
}

/// テスト
#[allow(dead_code)]
macro_rules! t {
  ($f: ident => $input: expr, $output: expr) => (
    #[test]
    fn $f() { test($input, $output, run); }
  );
}

#[allow(unused_macros)]
macro_rules! args {
  ($($arg: expr),*) => ({
    let mut s = String::new();
    $(s += &format!("{} ", $arg);)*
    s.pop().unwrap();
    s
  });
}

/// 構造体生成
#[allow(unused_macros)]
macro_rules! st {
  ($name: ident => $($p: ident : $t: ty),+) => (
    struct $name { $($p : $t),+ }
    impl FromStr for $name {
      type Err = ();
      fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut iter = s.split_whitespace();
        Ok(Self {
          $($p: iter.next().unwrap().parse::<$t>().unwrap(),)+
        })
      }
    }
  );
  ($name: ident => $($($p: ident),+: $t: ty);+) => (st!($name => $($($p : $t),+),+););
  ($name: ident => $($($p: ident),+: $($t: ty),+);+) => (st!($name => $($($p : $t),+),+););
  ($name: ident => $($p: ident),+: $t: ty) => (st!($name => $($p : $t),+););
  ($name: ident => $($p: ident),+: $($t: ty),+) => (st!($name => $($p : $t),+););
}

#[allow(dead_code)]
fn read<F: FromStr, R: Read>(reader: &mut R) -> F {
  let str = reader.by_ref()
    .bytes()
    .map(|c| c.unwrap() as char)
    .skip_while(|c| c.is_whitespace())
    .take_while(|c| !c.is_whitespace())
    .collect::<String>();
  str.parse::<F>().ok().unwrap()
}

#[allow(dead_code)]
fn read_line<F: FromStr, R: Read>(reader: &mut R) -> F {
  let str = reader.by_ref()
    .bytes()
    .map(|c| c.unwrap() as char)
    .skip_while(|c| c.is_whitespace())
    .take_while(|c| c != &'\n')
    .collect::<String>();
  let str = if str.ends_with('\r') { &str[0..str.len() - 1] } else { &str };
  str.parse::<F>().ok().unwrap()
}

/// 1要素読む
#[allow(unused_macros)]
macro_rules! r {
  ($stream: expr) => (read::<String, _>($stream));
  ($stream: expr, ) => (r!($stream));
  ($stream: expr; ) => (r!($stream));
  ($stream: expr; $t: ty) => (read::<$t,  _>($stream));
  ($stream: expr; $($t: ty),+) => (($(r!($stream; $t)),*));
  ($stream: expr; $t: ty; $n: expr) => ((0..$n).map(|_| r!($stream; $t)).collect::<Vec<_>>());
}

/// 1行読む
#[allow(unused_macros)]
macro_rules! rl {
  ($stream: expr) => (read_line::<String, _>($stream));
  ($stream: expr, ) => (r!($stream));
  ($stream: expr; ) => (r!($stream));
  ($stream: expr; $t: ty) => (read_line::<$t,  _>($stream));
  ($stream: expr; $t: ty; $n: expr) => ((0..$n).map(|_| rl!($stream; $t)).collect::<Vec<_>>());
}

macro_rules! _writes {
  ($stream: expr; $arg0: expr, $($arg: expr),*) => ({
    write!($stream, "{}", $arg0).ok();
    $(write!($stream, " {}", $arg).ok();)*
  });
}

/// write
#[allow(unused_macros)]
macro_rules! w {
  ($stream: expr) => (write!($stream, " ").ok());
  ($stream: expr; ) => (w!($stream));
  ($stream: expr, ) => (w!($stream));

  ($stream: expr; $arg: expr) => (write!($stream, "{}", $arg).ok());
  ($stream: expr; $arg: expr, ) => (w!($stream; $arg));

  ($stream: expr; $arg0: expr, $($arg: expr),+) => (_writes!($stream; $arg0, $($arg),+));
  ($stream: expr; $arg0: expr, $($arg: expr),+, ) => (w!($stream; $arg0, $($arg),*));

  ($stream: expr, $($arg: tt)*) => (write!($stream, $($arg)*).ok());
}

/// write_line
#[allow(unused_macros)]
macro_rules! wl {
  ($stream: expr) => (writeln!($stream).ok());
  ($stream: expr, ) => (wl!($stream));
  ($stream: expr; ) => (wl!($stream));

  ($stream: expr; $arg: expr) => (writeln!($stream, "{}", $arg).ok());
  ($stream: expr; $arg: expr, ) => (wl!($stream; $arg));

  ($stream: expr; $arg0: expr, $($arg: expr),+) => ({
    _writes!($stream; $arg0, $($arg),+);
    wl!($stream)
  });
  ($stream: expr; $arg0: expr, $($arg: expr),+, ) => (wl!($stream; $arg0, $($arg),*));

  ($stream: expr, $($arg: tt)*) => (writeln!($stream, $($arg)*).ok());
}

/// write Vec
#[allow(unused_macros)]
macro_rules! w_vec {
  ($stream: expr; $vec: expr) => ({
    let mut iter = $vec.iter();
    match iter.next() { Some(&i) => { w!($stream, "{}", i); }, None => {}, }
    for &i in iter { w!($stream, " {}", i); }
  });
}

/// write_line Vec
#[allow(unused_macros)]
macro_rules! wl_vec {
  ($stream: expr; $vec: expr) => ({
    w_vec!($stream; $vec);
    wl!($stream)
  });
}

trait VecAlias<T> {
  fn select<U>(&self, f: impl FnMut(&T) -> U)  -> Vec<U>;
}

impl<T> VecAlias<T> for Vec<T> {
  fn select<U>(&self, mut f: impl FnMut(&T) -> U)  -> Vec<U> {
    self.iter().map(|i| f(i)).collect::<Vec<_>>()
  }
}

trait VecOrdAlias<T> {
  fn asc(&mut self);
  fn desc(&mut self);
}

impl<T: Ord> VecOrdAlias<T> for Vec<T> {
  fn asc(&mut self) { self.sort_unstable(); }
  fn desc(&mut self) { self.sort_unstable_by(|i, j| j.cmp(i)); }
}

struct Point { i: i64, j: i64 }

fn pos(i: i64, j: i64) -> Point { Point { i, j }}

#[allow(unused_variables)]
fn run<R: Read, W: Write, E: Write>(r: &mut R, w: &mut W, err: &mut E) {
  let sw = w;
  let (h, w) = r!(r; i64, i64);
  // wl!(err; h, w);
  let (c_h, c_w) = r!(r; i64, i64);
  let (c_h, c_w) = (c_h - 1, c_w - 1);
  // wl!(err; c_h, c_w);
  let (d_h, d_w) = r!(r; i64, i64);
  let (d_h, d_w) = (d_h - 1, d_w - 1);
  // wl!(err; d_h, d_w);
  let maze = r!(r; String; h);
  let maze = maze.iter()
    .map(|s| s.chars().map(|c|  c == '.').collect::<Vec<_>>())
    .collect::<Vec<_>>();
  // for i in 0..h { wl_vec!(err; maze[i as usize]); }

  let mut visited = (0..h).map(|_| {
    (0..w).map(|_| false).collect::<Vec<_>>()
  }).collect::<Vec<_>>();
  let mut ans: i64 = 0;

  let mut q = VecDeque::new();
  q.push_front(pos(c_h, c_w));

  while !q.is_empty() {

    // wl!(err; "[move]");
    while !q.is_empty() {
      let p = q.pop_back().unwrap();
      if visited[p.i as usize][p.j as usize] { continue; }
      if p.i == d_h && p.j == d_w {
        w!(sw; ans);
        return;
      }
      visited[p.i as usize][p.j as usize] = true;
      // wl!(err; "visit", p.i, p.j);
      if p.i > 0 && maze[(p.i - 1) as usize][p.j as usize] && !visited[(p.i - 1) as usize][p.j as usize] {
        q.push_front(pos(p.i - 1, p.j));
        // wl!(err; "pop  ", p.i - 1, p.j);
      }
      if p.j > 0 && maze[p.i as usize][(p.j - 1) as usize] && !visited[p.i as usize][(p.j - 1) as usize] {
        q.push_front(pos(p.i, p.j - 1));
        // wl!(err; "pop  ", p.i, p.j - 1);
      }
      if p.i < h - 1 && maze[(p.i + 1) as usize][p.j as usize] && !visited[(p.i + 1) as usize][p.j as usize] {
        q.push_front(pos(p.i + 1, p.j));
        // wl!(err; "pop  ", p.i + 1, p.j);
      }
      if p.j < w - 1 && maze[p.i as usize][(p.j + 1) as usize] && !visited[p.i as usize][(p.j + 1) as usize] {
        q.push_front(pos(p.i, p.j + 1));
        // wl!(err; "pop  ", p.i, p.j + 1);
      }
    }

    // wl!(err; "[warp]");
    ans += 1;

    for i in 0..h {
      for j in 0..w {
        if !visited[i as usize][j as usize] { continue; }
        // wl!(err; "visit", i, j);
        for di in -2..3 {
          for dj in -2..3 {
            let ii = i + di;
            let jj = j + dj;
            if !(ii >= 0 && ii < h && jj >= 0 && jj < w) { continue; }
            // wl!(err; "check", ii, jj, maze[ii as usize][jj as usize], visited[ii as usize][jj as usize]);
            if maze[ii as usize][jj as usize] && !visited[ii as usize][jj as usize] {
              q.push_front(pos(ii, jj));
              // wl!(err; "pop  ", ii, jj);
            }
          }
        }
      }
    }
  }
  w!(sw; -1);
}

t!(td1 => r"4 4
1 1
4 4
..#.
..#.
.#..
.#..", r"1");
t!(td2 => r"4 4
1 4
4 1
.##.
####
####
.##.", r"-1");
t!(td3 => r"4 4
2 2
3 3
....
....
....
....", r"0");
t!(td4 => r"4 5
1 2
2 5
#.###
####.
#..##
#..##", r"2");