import java.io.BufferedReader
import java.io.BufferedWriter

@ExperimentalStdlibApi
fun main() = Case().exec(::solve)
//fun main() = TestExecutor.assert(testCase) { Case(it.r, it.w).exec(::solve) }

/** https://atcoder.jp/contests/abc176/tasks/abc176_d **/
@ExperimentalStdlibApi
fun solve(c: Case) {
    val (h, w) = c.intList()
    val (ch, cw) = c.intList().map { it - 1 }
    val (dh, dw) = c.intList().map { it - 1 }
    val maze = (0 until h).map { c.string().toCharArray() }
    val scores = (0 until h).map { arrayOfNulls<Int>(w).also { it.fill(Int.MAX_VALUE) } }

    val deque = ArrayDeque<SearchPos>()
    deque.addFirst(SearchPos(ch, cw, 0))

    fun bfs(): Int? {
        val (y, x, score) = deque.removeFirstOrNull() ?: return -1

        if (y < 0 ||
            y >= h ||
            x < 0 ||
            x >= w ||
            maze[y][x] == '#'
        ) {
            return null // not valid place
        }

        if (scores[y][x] != Int.MAX_VALUE) {
            return null // already searched
        }
        if (y == dh && x == dw) {
            return score // found!
        }
        scores[y][x] = score

        deque.addFirst(SearchPos(y + 1, x, score))
        deque.addFirst(SearchPos(y - 1, x, score))
        deque.addFirst(SearchPos(y, x + 1, score))
        deque.addFirst(SearchPos(y, x - 1, score))

        deque.addLast(SearchPos(y - 2, x - 2, score + 1))
        deque.addLast(SearchPos(y - 2, x - 1, score + 1))
        deque.addLast(SearchPos(y - 2, x, score + 1))
        deque.addLast(SearchPos(y - 2, x + 1, score + 1))
        deque.addLast(SearchPos(y - 2, x + 2, score + 1))

        deque.addLast(SearchPos(y - 1, x - 2, score + 1))
        deque.addLast(SearchPos(y - 1, x - 1, score + 1))
        deque.addLast(SearchPos(y - 1, x + 1, score + 1))
        deque.addLast(SearchPos(y - 1, x + 2, score + 1))

        deque.addLast(SearchPos(y, x - 2, score + 1))
        deque.addLast(SearchPos(y, x + 2, score + 1))

        deque.addLast(SearchPos(y + 1, x - 2, score + 1))
        deque.addLast(SearchPos(y + 1, x - 1, score + 1))
        deque.addLast(SearchPos(y + 1, x + 1, score + 1))
        deque.addLast(SearchPos(y + 1, x + 2, score + 1))

        deque.addLast(SearchPos(y + 2, x - 2, score + 1))
        deque.addLast(SearchPos(y + 2, x - 1, score + 1))
        deque.addLast(SearchPos(y + 2, x, score + 1))
        deque.addLast(SearchPos(y + 2, x + 1, score + 1))
        deque.addLast(SearchPos(y + 2, x + 2, score + 1))

        return null
    }

    while (true) {
        val result = bfs() ?: continue
        c.println(result.toString())
        break
    }
}

data class SearchPos(val y: Int, val x: Int, val score: Int)

class Case(
    private val input: BufferedReader = System.`in`.bufferedReader(),
    private val out: BufferedWriter = System.out.bufferedWriter()
) {
    fun exec(fn: (Case) -> Unit) = input.use { out.use { execInThread(fn) } }
    private fun execInThread(fn: (Case) -> Unit) =
        Thread(null, { fn(this) }, "solve", 64 * 1024 * 1024)
            .apply { setUncaughtExceptionHandler { _, e -> e.printStackTrace(); kotlin.system.exitProcess(1) } }
            .apply { start() }.join()

    fun println(c: CharSequence?) = out.appendln(c)
    fun string(): String = input.readLine().trimEnd()
    fun long(): Long = input.readLine().toLong()
    fun intList(): List<Int> = input.readLine().split(" ").map { it.toInt() }
    fun longList(): List<Long> = input.readLine().split(" ").map { it.toLong() }
}
