use std::cmp;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::fmt::Debug;
use std::str::FromStr;
#[allow(dead_code)]
fn read_as_vec<T>() -> Vec<T>
where
    T: FromStr,
    <T as FromStr>::Err: Debug,
{
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim()
        .split_whitespace()
        .map(|c| T::from_str(c).unwrap())
        .collect()
}

#[allow(dead_code)]
fn read_as_string() -> String {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim().to_string()
}

fn solve(h: usize, w: usize, c: &(usize, usize), d: &(usize, usize), s: &Vec<Vec<char>>) -> i64 {
    let mut map: Vec<Vec<char>> = vec![];
    map.push(vec!['#'; w + 4]);
    map.push(vec!['#'; w + 4]);

    for i in 0..h {
        let mut row = vec!['#', '#'];
        let mut tmp = s[i].clone();
        row.append(&mut tmp);
        row.push('#');
        row.push('#');
        map.push(row);
    }
    map.push(vec!['#'; w + 4]);
    map.push(vec!['#'; w + 4]);

    //shadows
    let (h, w) = (h + 4, w + 4);
    let c = (c.0 + 2, c.1 + 2);
    let d = (d.0 + 2, d.1 + 2);
    let s = map;

    let mut cost_map: Vec<Vec<usize>> = vec![vec![std::usize::MAX; w]; h];
    cost_map[c.0][c.1] = 0;
    let mut heap: BinaryHeap<(Reverse<usize>, (usize, usize))> = BinaryHeap::new();

    heap.push((Reverse(0), (c.0, c.1)));
    // for i in 0..h {
    //     println!("{:?}", s[i]);
    // }
    while let Some(cur) = heap.pop() {
        //println!("{:?}", cur);
        let cur_cost: usize;
        if let Reverse(v) = cur.0 {
            cur_cost = v;
        } else {
            unreachable!();
        }
        let cur_pos = cur.1;

        if cur_pos.0 == d.0 && cur_pos.1 == d.1 {
            return cur_cost as i64;
        }
        for next_pos in vec![
            (cur_pos.0, cur_pos.1 - 1),
            (cur_pos.0, cur_pos.1 + 1),
            (cur_pos.0 - 1, cur_pos.1),
            (cur_pos.0 + 1, cur_pos.1),
        ] {
            if s[next_pos.0][next_pos.1] == '.' && cost_map[next_pos.0][next_pos.1] > cur_cost {
                heap.push((Reverse(cur_cost), (next_pos.0, next_pos.1)));
                cost_map[next_pos.0][next_pos.1] = cur_cost;
            }
        }
        //println!("{:?}", cur_pos);
        for i in cur_pos.0 - 2..=cur_pos.0 + 2 {
            for j in cur_pos.1 - 2..=cur_pos.1 + 2 {
                //println!("check we can jump to {}, {}", i, j);
                if s[i][j] == '.' && cost_map[i][j] > cur_cost + 1 {
                    heap.push((Reverse(cur_cost + 1), (i, j)));
                    cost_map[i][j] = cur_cost + 1;
                    //println!("we can jump to {}, {}", i, j);
                }
            }
        }
    }
    return -1;
}

fn main() {
    let line = read_as_vec::<usize>();
    let (h, w) = (line[0], line[1]);

    let line = read_as_vec::<usize>();
    let c = (line[0] - 1, line[1] - 1);
    let line = read_as_vec::<usize>();
    let d = (line[0] - 1, line[1] - 1);
    let mut s: Vec<Vec<char>> = vec![];
    for _ in 0..h {
        s.push(read_as_string().chars().collect::<Vec<char>>());
    }

    let ans = solve(h, w, &c, &d, &s);

    println!("{}", ans);
}


Measured memory_bytes: 22144