import java.io.{BufferedOutputStream, BufferedReader, FileOutputStream, InputStreamReader, PrintWriter}
import java.lang

import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.reflect.ClassTag

object Main {
  val DEBUG = false

  lazy val debugOut: PrintWriter = {
    new PrintWriter(new BufferedOutputStream(new FileOutputStream("log.txt", true)))
  }

  def log(message: => Any): Unit = {
    if (DEBUG) {
      debugOut.println(message)
    }
  }

  def debug(closure: => Unit): Unit = {
    if (DEBUG) {
      closure
    }
  }

  def get[T: ClassTag](implicit in: BufferedReader, converter: String => T): T = {
    converter(in.readLine)
  }

  def getArray[T: ClassTag](implicit in: BufferedReader, converter: String => T): Array[T] = {
    get[String].split("\\s+").map[T](converter)
  }

  implicit val idConverter: String => String = s => s
  implicit val intConverter: String => Int = s => Integer.parseInt(s)
  implicit val longConverter: String => Long = s => lang.Long.parseLong(s)

  def get[T1, T2](
                   implicit in: BufferedReader,
                   converter1: String => T1,
                   converter2: String => T2
                 ): (T1, T2) = {
    getArray[String] match {
      case Array(v1, v2) => (converter1(v1), converter2(v2))
    }
  }

  def get[T1, T2, T3](
                       implicit in: BufferedReader,
                       converter1: String => T1,
                       converter2: String => T2,
                       converter3: String => T3
                     ): (T1, T2, T3) = {
    getArray[String] match {
      case Array(v1, v2, v3) => (converter1(v1), converter2(v2), converter3(v3))
    }
  }

  def get[T1, T2, T3, T4](
                           implicit in: BufferedReader,
                           converter1: String => T1,
                           converter2: String => T2,
                           converter3: String => T3,
                           converter4: String => T4
                         ): (T1, T2, T3, T4) = {
    getArray[String] match {
      case Array(v1, v2, v3, v4) => (converter1(v1), converter2(v2), converter3(v3), converter4(v4))
    }
  }

  implicit class TimesInt(val n: Int) {
    def times(f: Int => Unit): Unit = {
      for (i <- 0 until n) {
        f(i)
      }
    }
  }

  def primes(n: Long): ArrayBuffer[Long] = {
    val buf = ArrayBuffer.empty[Long]
    val s = Math.sqrt(n).toInt

    var v = n
    for (i <- 2 to s) {
      if (v == 1 || v == 0) {
        return buf
      } else {
        while (v % i == 0) {
          buf.append(i)
          v /= i
        }
      }
    }
    if (v > s) {
      buf.append(v)
    }
    buf
  }

  def divisors(n: Int): ArrayBuffer[Int] = {
    val buf = ArrayBuffer.empty[Int]
    val s = Math.sqrt(n).toInt

    for (i <- 1 to s) {
      if (n % i == 0) {
        buf.append(i)
        if (i != n / i) {
          buf.append(n / i)
        }
      }
    }
    buf
  }

  @tailrec
  def gcd(a: Long, b: Long): Long = {
    val reminder = a % b
    if (reminder == 0) {
      b
    } else {
      gcd(b, reminder)
    }
  }

  @tailrec
  def gcd(a: Int, b: Int): Int = {
    val reminder = a % b
    if (reminder == 0) {
      b
    } else {
      gcd(b, reminder)
    }
  }

  def lcm(a: Long, b: Long): Long = {
    a / gcd(a, b) * b
  }

  def toBitArray(n: Int, width: Int): Array[Boolean] = {
    val buf = ArrayBuffer.fill(width)(false)

    @tailrec
    def inner(n: Int, i: Int): Array[Boolean] = {
      buf(i) = (n & 1) == 0
      if (i == 0) {
        buf.toArray
      } else {
        inner(n / 2, i - 1)
      }
    }

    inner(n, width - 1)
  }

  def modpow(n: Long, p: Long, m: Long): Long = {
    @tailrec
    def inner(n: Long, p: Long, acc: Long): Long = {
      if (p == 0) {
        acc
      } else if ((p & 1) == 0) {
        inner(n * n % m, p >> 1, acc)
      } else {
        inner(n * n % m, p >> 1, acc * n % m)
      }
    }

    inner(n % m, p, 1)
  }

  def main(args: Array[String]): Unit = {
    implicit val in: BufferedReader = new BufferedReader(new InputStreamReader(System.in))
    val out = new PrintWriter(new BufferedOutputStream(System.out))
    val (h, w) = get[Int, Int]
    val (ch, cw) = get[Int, Int] match {
      case (a, b) => (a - 1, b - 1)
    }
    val (dh, dw) = get[Int, Int] match {
      case (a, b) => (a - 1, b - 1)
    }
    val smap = Array.fill(h) {
      get[String].toCharArray
    }

    def xy2i(y: Int, x: Int): Int = {
      y * w + x
    }

    def i2xy(i: Int): (Int, Int) = {
      (i / w, i % w)
    }

    log("=== start")

    class UnionFind(size: Int) {
      val roots: Array[Int] = Array.ofDim[Int](size)
      for (i <- 0 until size) {
        roots(i) = i
      }

      val warpable: Array[mutable.HashSet[Int]] = Array.fill(size)(mutable.HashSet.empty[Int])

      def root(a: Int): Int = {
        if (roots(a) == a) {
          a
        } else {
          roots(a) = root(roots(a))
          roots(a)
        }
      }

      def isSameRoot(a: Int, b: Int): Boolean = {
        root(a) == root(b)
      }

      def walkablize(a: Int, b: Int): Unit = {
        log(s"walkablize(${i2xy(a)},${i2xy(b)})")
        if (a != b) {
          val rootA = root(a)
          val rootB = root(b)
          if (rootA != rootB) {
            roots(rootB) = rootA
            warpable(rootA).addAll(warpable(rootB))
            warpable(rootB).clear()
          }
        }
      }

      def warpablize(a: Int, b: Int): Unit = {
        log(s"warpablize(${i2xy(a)},${i2xy(b)})")
        val rootA = root(a)
        val rootB = root(b)
        if (rootA != rootB) {
          warpable(rootA).add(rootB)
          warpable(rootB).add(rootA)
        }
      }

      def getWarpables(a: Int): mutable.HashSet[Int] = {
        val rootA = root(a)
        warpable(rootA) = warpable(rootA).map(root)

        warpable(rootA)
      }
    }

    val unionFind = new UnionFind(h * w)

    for (y <- 0 until h) {
      for (x <- 0 until w) {
        if (smap(y)(x) == '.') {

          for (dy <- -2 to 2) {
            for (dx <- -2 to 2) {
              val tx = x + dx
              val ty = y + dy

              if (!(dx == 0 && dy == 0) && tx >= 0 && ty >= 0 && tx < w && ty < h) {
                if (smap(ty)(tx) == '.') {
                  if (Math.abs(dx) + Math.abs(dy) == 1) {
                    unionFind.walkablize(xy2i(y, x), xy2i(ty, tx))
                  } else {
                    unionFind.warpablize(xy2i(y, x), xy2i(ty, tx))
                  }
                }
              }
            }
          }
        }
      }
    }

    for (y <- 0 until h) {
      for (x <- 0 until w) {
        if (smap(y)(x) == '.') {
          log(s"(${y},${x}) = root->${unionFind.root(xy2i(y, x))}, warpables->${unionFind.getWarpables(xy2i(y, x))}")
        }
      }
    }

    val queue = mutable.Queue.empty[Int]
    queue.enqueue(xy2i(ch, cw))
    val warp = Array.fill(h * w)(-1)
    warp(xy2i(ch, cw)) = 0

    while (queue.nonEmpty) {
      val current = queue.dequeue()
      val currentWarp = warp(current)
      log(s"current = ${current}")
      log(s"currentWarp = ${currentWarp}")

      if (unionFind.isSameRoot(xy2i(dh, dw), current)) {
        out.println(currentWarp)
        out.flush()
        log("=== end")
        debug {
          debugOut.flush()
        }
        return
      } else {
        val warpables = unionFind.getWarpables(current)
        warpables.foreach { w =>
          log(s"-> warpables=${w}")

          if (warp(w) == -1) {
            warp(w) = currentWarp + 1
            queue.enqueue(w)
          }
        }
      }
    }

    out.println(-1)
    out.flush()
    log("=== end")
    debug {
      debugOut.flush()
    }

  }
}