#![allow(unused_imports)]
#![allow(unused_macros)]
use std::cmp::{max, min, Reverse};
use std::collections::*;
use std::io::{stdin, Read};

trait ChMinMax {
    fn chmin(&mut self, other: Self);
    fn chmax(&mut self, other: Self);
}
impl<T> ChMinMax for T
where
    T: PartialOrd,
{
    fn chmin(&mut self, other: Self) {
        if *self > other {
            *self = other
        }
    }
    fn chmax(&mut self, other: Self) {
        if *self < other {
            *self = other
        }
    }
}

#[allow(unused_macros)]
macro_rules! parse {
    ($it: ident ) => {};
    ($it: ident, ) => {};
    ($it: ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
    ($it: ident, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = parse_val!($it, $t);
        parse!($it $($r)*);
    };
    ($it: ident, $var:ident $($r:tt)*) => {
        let $var = parse_val!($it, usize);
        parse!($it $($r)*);
    };
}

#[allow(unused_macros)]
macro_rules! parse_val {
    ($it: ident, [$t:tt; $len:expr]) => {
        (0..$len).map(|_| parse_val!($it, $t)).collect::<Vec<_>>();
    };
    ($it: ident, ($($t: tt),*)) => {
        ($(parse_val!($it, $t)),*)
    };
    ($it: ident, u1) => {
        $it.next().unwrap().parse::<usize>().unwrap() -1
    };
    ($it: ident, $t: ty) => {
        $it.next().unwrap().parse::<$t>().unwrap()
    };
}

#[cfg(debug_assertions)]
macro_rules! debug {
    ($( $args:expr ),*) => { eprintln!( $( $args ),* ); }
}

#[cfg(not(debug_assertions))]
macro_rules! debug {
    ($( $args:expr ),*) => {
        ()
    };
}

fn solve(s: &str) {
    let mut it = s.split_whitespace();
    parse!(it, h: usize, w: usize, c: (u1, u1), d: (u1, u1));
    let c: (usize, usize) = c;
    let (dx, dy) = d;
    let mut s: Vec<Vec<bool>> = vec![];
    for _ in 0..h {
        s.push(it.next().unwrap().chars().map(|x| x == '.').collect())
    }
    let mut q = BinaryHeap::new();
    q.push((Reverse(0usize), c));
    const M: usize = std::usize::MAX;
    let mut d = vec![vec![M; w]; h];
    d[c.0][c.1] = 0;
    while let Some((r, (x, y))) = q.pop() {
        if x == dx && y == dy {
            break;
        }
        for (nx, ny) in vec![
            (x + 1, y),
            (x, y + 1),
            (x.overflowing_sub(1).0, y),
            (x, y.overflowing_sub(1).0),
        ] {
            if nx >= h || ny >= w {
                continue;
            }
            if s[nx][ny] && d[nx][ny] > r.0 {
                q.push((r, (nx, ny)));
                d[nx][ny] = r.0;
            }
        }
        for nx in vec![
            x.overflowing_sub(2).0,
            x.overflowing_sub(1).0,
            x,
            x + 1,
            x + 2,
        ] {
            if nx >= h {
                continue;
            }
            for ny in vec![
                y.overflowing_sub(2).0,
                y.overflowing_sub(1).0,
                y,
                y + 1,
                y + 2,
            ] {
                if ny >= w {
                    continue;
                }
                if s[nx][ny] && d[nx][ny] > r.0 + 1 {
                    q.push((Reverse(r.0 + 1), (nx, ny)));
                    d[nx][ny] = r.0 + 1;
                }
            }
        }
    }
    if d[dx][dy] == M {
        println!("{}", -1);
    } else {
        println!("{}", d[dx][dy]);
    }
}

fn main() {
    let mut s = String::new();
    stdin().read_to_string(&mut s).unwrap();
    solve(&s);
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_input() {
        let s = "
        ";
        solve(s);
    }
}


Measured memory_bytes: 12236