package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
	"strings"
)

func main() {
	io := NewIo(os.Stdin, os.Stdout)
	defer io.Flush()
	h, w := io.NextInt(), io.NextInt()
	ch, cw := io.NextInt()-1, io.NextInt()-1
	dh, dw := io.NextInt()-1, io.NextInt()-1
	stage := make([]string, h)
	for i := 0; i < h; i++ {
		stage[i] = io.Next()
	}
	Log(h, w)
	Log(ch, cw)
	Log(dh, dw)
	for i := range stage {
		Log(stage[i])
	}
	ans := solve(h, w, ch, cw, dh, dw, stage)
	io.Println(ans)
}

func solve(h, w, ch, cw, dh, dw int, stage []string) int {
	costs := make([][]int, h)
	for i := range costs {
		costs[i] = make([]int, w)
		for j := range costs[i] {
			costs[i][j] = inf
		}
	}
	costs[ch][cw] = 0
	q := &PriorityQueue{}
	heap.Push(q, state{ch, cw, 0})
	for q.Len() > 0 {
		now := heap.Pop(q).(state)
		Log(now)
		// move A
		for i := range dxA {
			x, y := now.x+dxA[i], now.y+dyA[i]
			if x < 0 || h <= x || y < 0 || w <= y {
				continue
			}
			if stage[x][y] == '#' {
				continue
			}
			cost := now.cost
			if cost < costs[x][y] {
				costs[x][y] = cost
				heap.Push(q, state{x, y, cost})
			}
		}
		// move B
		for i := range dxB {
			x, y := now.x+dxB[i], now.y+dyB[i]
			if x < 0 || h <= x || y < 0 || w <= y {
				continue
			}
			if stage[x][y] == '#' {
				continue
			}
			cost := now.cost + 1
			if cost < costs[x][y] {
				costs[x][y] = cost
				heap.Push(q, state{x, y, cost})
			}
		}
	}
	if costs[dh][dw] == inf {
		return -1
	}
	return costs[dh][dw]
}

const inf = math.MaxInt64

type state struct{ x, y, cost int }

func (s state) Less(t Comparable) bool {
	return s.cost < t.(state).cost
}

var dxA = []int{0, 0, -1, 1}
var dyA = []int{-1, 1, 0, 0}

var dxB = []int{
	-2, -2, -2, -2, -2,
	-1, -1, -1, -1, -1,
	0, 0, 0, 0, 0,
	1, 1, 1, 1, 1,
	2, 2, 2, 2, 2,
}
var dyB = []int{
	-2, -1, 0, 1, 2,
	-2, -1, 0, 1, 2,
	-2, -1, 0, 1, 2,
	-2, -1, 0, 1, 2,
	-2, -1, 0, 1, 2,
}

type Comparable interface{ Less(Comparable) bool }

// PriorityQueue

type PriorityQueue []Comparable

func (q PriorityQueue) Len() int           { return len(q) }
func (q PriorityQueue) Less(i, j int) bool { return q[i].Less(q[j]) }
func (q PriorityQueue) Swap(i, j int)      { q[i], q[j] = q[j], q[i] }

// Push adds an element
func (q *PriorityQueue) Push(x interface{}) { *q = append(*q, x.(Comparable)) }

// Pop gets and remove the minimum element
func (q *PriorityQueue) Pop() interface{} {
	x := (*q)[len(*q)-1]
	*q = (*q)[:len(*q)-1]
	return x
}

// Io is I/O object
type Io struct {
	reader    *bufio.Reader
	writer    *bufio.Writer
	tokens    []string
	nextToken int
}

// NewIo returns a new Io instance
func NewIo(r io.Reader, w io.Writer) *Io {
	return &Io{
		reader: bufio.NewReader(r),
		writer: bufio.NewWriter(w),
	}
}

// Flush flushes writer
func (io *Io) Flush() {
	err := io.writer.Flush()
	if err != nil {
		panic(err)
	}
}

// NextLine scans a line from stdin
func (io *Io) NextLine() string {
	var buffer []byte
	for {
		line, isPrefix, err := io.reader.ReadLine()
		if err != nil {
			panic(err)
		}
		buffer = append(buffer, line...)
		if !isPrefix {
			break
		}
	}
	return string(buffer)
}

// Next return a word from stdin
func (io *Io) Next() string {
	for io.nextToken >= len(io.tokens) {
		line := io.NextLine()
		io.tokens = strings.Fields(line)
		io.nextToken = 0
	}
	r := io.tokens[io.nextToken]
	io.nextToken++
	return r
}

// NextInt returns an integer from stdin
func (io *Io) NextInt() int {
	i, err := strconv.Atoi(io.Next())
	if err != nil {
		panic(err)
	}
	return i
}

// Println is a wrapper of fmt.Fprintln
func (io *Io) Println(a ...interface{}) {
	fmt.Fprintln(io.writer, a...)
}

// Log outputs a to stderr
func Log(a ...interface{}) {
	fmt.Fprintln(os.Stderr, a...)
}


Measured memory_bytes: 34892