{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE MultiWayIf          #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE ScopedTypeVariables #-}
import           Control.Monad
import           Control.Monad.ST
import           Control.Monad.State
import           Data.Array.IArray
import           Data.Array.ST
import           Data.Array.Unboxed
import qualified Data.ByteString.Char8 as BS
import           Data.Char
import           Data.List

main :: IO ()
main = do
  [h,w] <- readLnAsListWith unconsInt
  [cx,cy] <- readLnAsListWith unconsInt
  [dx,dy] <- readLnAsListWith unconsInt
  sgrid <- readLnAs2DArrayWith unconsChar h w :: IO (UArray (Int,Int) Char)

  let ggrid = gridBfs (h,w) (cx,cy) (\g (i,j) -> g ! (i,j) == '#') sgrid

  print $ ggrid ! (dx,dy)

  return ()


type Grid a = UArray (Int,Int) a
type MGrid s = STUArray s (Int,Int)


gridBfs :: (Int,Int) -> (Int,Int) -> (Grid a -> (Int,Int) -> Bool) -> Grid a -> UArray (Int,Int) Int
gridBfs (h',w') (sh,sw) f g = runSTUArray $ do
  dist <- newArray ((1,1),(h',w')) (-1)
  writeArray dist (sh,sw) 0

  let queue = pushBack empty (sh,sw)
  go dist 0 queue

  return dist

  where go :: MGrid s Int -> Int -> Queue (Int,Int) -> ST s ()
        go dist cost q =
          if isEmpty q
          then do
            prev <- map fst . filter (\(_,e) -> e == cost) <$> getAssocs dist
            candidate <- filterM (readArray dist >=> (return . (==(-1)))) (concatMap neighbour25 prev)
            if null candidate then return () else do
              forM_ candidate $ \next -> writeArray dist next (cost+1)
              go dist (cost+1) $ foldl' pushBack empty $ nub candidate
          else do
            let (curr, q') = popFront q
            candidate <- filterM (readArray dist >=> (return . (==(-1)))) (neighbour4 curr)
            forM_ candidate $ \next -> writeArray dist next cost
            go dist cost $ foldl' pushBack q' candidate



        neighbour4 :: (Int,Int) -> [(Int,Int)]
        neighbour4 (h,w) = filter inGrid [(h+x,w+y) | (x,y) <- [(-1,0),(1,0),(0,-1),(0,1)]]

        neighbour25 :: (Int,Int) -> [(Int,Int)]
        neighbour25 (h,w) = filter inGrid [(h+x,w+y) | x <- [-2..2], y <- [-2..2], (x,y) /= (0,0)]

        inGrid :: (Int,Int) -> Bool
        inGrid (h,w) = h >= 1 && h <= h' && w >= 1 && w <= w' && not (g `f` (h,w))


data Queue a = Q { front :: [a]
                 , rear  :: [a]
                 , thunk :: [a]
                 } deriving (Eq)

isEmpty :: Eq a => Queue a -> Bool
isEmpty = (==empty)

empty :: Queue a
empty = Q [] [] []

pushBack :: Queue a -> a -> Queue a
pushBack (Q f r t) e = check $! Q f (e:r) t

popFront :: Queue a -> (a, Queue a)
popFront (Q (e:f) r t) = (e, check $! Q f r t)
popFront (Q [] _ _)    = error "empty queue"

check :: Queue a -> Queue a
check (Q f r (_:t)) = Q f r t
check (Q f r []) = let ff = rotate f r []
                   in Q ff [] ff
  where rotate :: [a] -> [a] -> [a] -> [a]
        rotate [] (y:_) zs      = y:zs
        rotate (x:xs) (y:ys) zs = x : rotate xs ys (y:zs)

instance Show a => Show (Queue a) where
  show (Q f r t) = "Q { " <> show f <> "\n" <>
                   "    " <> show r <> "\n" <>
                   "    " <> show t <> "\n" <>
                   "  }"



-- gridDfs :: (Int,Int) -> (Int,Int) -> (Grid a -> (Int,Int) -> Bool) -> Grid a -> UArray (Int,Int) Int
-- gridDfs (h',w') (sh,sw) f g = runSTUArray $ do
--   seen <- newArray ((1,1),(h',w')) (-1) :: ST s (STUArray s (Int,Int) Int)
--   go seen (sh,sw) 0
--   return seen

--   where go :: MGrid s Int -> (Int,Int) -> Int -> ST s ()
--         go seen (h,w) color = do
--           c <- readArray seen (h,w)
--           if c /= (-1) then return () else do
--             writeArray seen (h,w) color
--             let nexts = neighbour4 (h,w)
--             forM_ nexts $ \(nh,nw) ->
--               if g `f` (nh,nw)
--               then do return ()
--               else do go seen (nh,nw) color

--             let nexts2 = neighbour25 (h,w)
--             forM_ nexts2 $ \(nh,nw) ->
--               if g `f` (nh,nw)
--               then do return ()
--               else do go seen (nh,nw) (color+1)


--         neighbour4 :: (Int,Int) -> [(Int,Int)]
--         neighbour4 (h,w) = filter inGrid [(h+x,w+y) | (x,y) <- [(-1,0),(1,0),(0,-1),(0,1)]]

--         neighbour25 :: (Int,Int) -> [(Int,Int)]
--         neighbour25 (h,w) = filter inGrid [(h+x,w+y) | x <- [-2..2], y <- [-2..2], (x,y) /= (0,0)]

--         inGrid :: (Int,Int) -> Bool
--         inGrid (h,w) = h >= 1 && h <= h' && w >= 1 && w <= w'



-- converter
unconsChar :: StateT BS.ByteString Maybe Char
unconsChar = StateT BS.uncons

unconsInt :: StateT BS.ByteString Maybe Int
unconsInt = StateT $ BS.readInt . BS.dropWhile isSpace

readLnAsListWith :: StateT BS.ByteString Maybe a -> IO [a]
readLnAsListWith !st = unfoldr (runStateT st) <$> BS.getLine

readLnAs2DArrayWith :: IArray a e => StateT BS.ByteString Maybe e -> Int -> Int -> IO (a (Int,Int) e)
readLnAs2DArrayWith !st !n !m = listArray ((1,1),(n,m)) . unfoldr (runStateT st) . BS.concat <$> replicateM n BS.getLine
