use proconio::input;
use proconio::marker::Chars;
#[allow(unused_imports)]
use std::cmp::{max, min};
#[allow(unused)]
const ALPHA_SMALL: [char; 26] = [
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
    't', 'u', 'v', 'w', 'x', 'y', 'z',
];
#[allow(unused)]
const ALPHA: [char; 26] = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
    'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
];
fn main() {
    input!(H: usize, W: usize);
    input!(cy: usize, cx: usize);
    input!(dy: usize, dx: usize);
    let mut grid = vec![];
    for _ in 0..H {
        input!(t: Chars);
        grid.push(t);
    }

    //let (H, W, cx, cy, dx, dy, grid) = random_test(10, 1);
    //println!("{:?}", grid);
    let ans = calc(H, W, cx, cy, dx, dy, &grid);
    if ans == std::usize::MAX / 2 {
        println!("-1");
    } else {
        println!("{}", ans);
    }
}

fn calc(
    H: usize,
    W: usize,
    cx: usize,
    cy: usize,
    dx: usize,
    dy: usize,
    grid: &Vec<Vec<char>>,
) -> usize {
    let mut adj_list = vec![vec![]; H * W];
    //println!("1");
    for i in 0..W {
        for j in 0..H {
            for dx in -2..=2 {
                for dy in -2..=2 {
                    let mut y = 0;
                    let mut x = 0;
                    let mut cost = 0;
                    if dx < 0 && i as i64 <= dx {
                        continue;
                    }
                    if 0 <= i as i64 + dx && i as i64 + dx < W as i64 {
                        x = (i as i64 + dx) as usize;
                    } else {
                        continue;
                    }
                    if dy < 0 && j as i64 <= dy {
                        continue;
                    }
                    if 0 <= j as i64 + dy && j as i64 + dy < H as i64 {
                        y = (j as i64 + dy) as usize;
                    } else {
                        continue;
                    }
                    if dx.abs() + dy.abs() >= 2 {
                        cost = 1;
                    }
                    //println!("{} {}", x, y);
                    if grid[y][x] == '#' {
                        continue;
                    }

                    //println!("{} {}", i, j);
                    //println!("{} {}", x, y);
                    adj_list[i + W * j].push((x + W * y, cost));
                }
            }
        }
    }

    // println!("{:?}", adj_list);
    //println!("{:?}", adj_list[H]);

    let ans = dijkstra_no_struct(&adj_list, (cx - 1) + (cy - 1) * W, (dx - 1) + (dy - 1) * W);
    ans
}

fn dijkstra_no_struct(adj_list: &Vec<Vec<(usize, usize)>>, start: usize, goal: usize) -> usize {
    let mut dist = vec![std::usize::MAX / 2; adj_list.len()];
    let mut p_queue: std::collections::BinaryHeap<(i64, usize)> =
        std::collections::BinaryHeap::new();

    //init
    dist[start] = 0;
    p_queue.push((0, start));

    while !p_queue.is_empty() {
        // 起点となるノード
        let (cost, now) = match p_queue.pop() {
            None => break,
            Some(e) => (-e.0 as usize, e.1),
        };

        if cost > dist[now] {
            continue;
        }

        // 繋がっているノードを探索
        for &edge in &adj_list[now] {
            let next = edge.0;
            let weight = edge.1;

            if dist[next] > weight + cost {
                p_queue.push((-((weight + cost) as i64), next));
                dist[next] = weight + cost;
            }
        }
    }

    dist[goal]
}

fn random_test(H: usize, W: usize) -> (usize, usize, usize, usize, usize, usize, Vec<Vec<char>>) {
    let N = H * W;
    use rand::Rng;
    let mut rng = rand::thread_rng();
    let mut grid = vec![vec!['#'; W]; H];
    for i in 0..H {
        for j in 0..W {
            let i = rng.gen::<usize>() % 2;
            if i == 0 {
                grid[i][j] = '.';
            }
        }
    }

    (H, W, 1, 1, H, W, grid)
}


Measured memory_bytes: 310336