local read = setmetatable({}, {__index = function(t, k) local a = {} for i=1,#k do table.insert(a, '*'..string.sub(k, i, i)) end local r = io.read local u = table.unpack or unpack return function() return r(u(a)) end end})
read.N = function(N) local t={} for i=1,N do t[i]=read.n() end return t end
string.totable = function(s) local t={} local u=string.sub for i=1,#s do t[i] = u(s, i, i) end return t end
string.split = function(s) local t={} for w in string.gmatch(s, "[^%s]+") do table.insert(t, w) end return (table.unpack or unpack)(t) end
local function array(dimensi0n, default_val) assert(type(default_val) ~= 'table') local n=dimensi0n local m={}if default_val~=nil then m[1]={__index=function()return default_val end}end for i=2,n do m[i]={__index=function(p, k)local c=setmetatable({},m[i-1])rawset(p,k,c)return c end}end return setmetatable({},m[n])end
local function tostringxx(o, depth) depth = depth or 0 if depth > 10 then return "<too deep!>" end if o == _G then return "<_G>" end local indent0 = (" "):rep((depth) * 2) local indent1 = (" "):rep((depth+1) * 2) local indent2= (" "):rep((depth+2) * 2) if type(o) == 'table' then local keys = {} local types = {} for k in pairs(o) do types[type(k)] = true table.insert(keys, k) end local types_count = 0 local lasttype for k in pairs(types) do types_count = types_count + 1 lasttype = k end if types_count == 1 and (lasttype == 'string' or lasttype == 'number') then table.sort(keys) end local inside = {} for i=1,#keys do local k = keys[i] local v = o[k] if type(k) == 'string' then k = string.format('%q', k) end table.insert(inside, indent1 .. '['..tostring(k)..'] = ' .. tostringxx(v, depth + 1)) end return '{\n' .. table.concat(inside, ',\n') .. '\n' .. indent0 .. '}' else if type(o) == 'string' then o = string.format('%q', o) end return tostring(o) end end
local function richtraceback() local x = 2 while true do local info = debug.getinfo(x) if not info then break end local fname = '<' .. info.short_src .. ":" .. info.linedefined .. ">" if info.name then fname = info.name end print(info.short_src .. ":" .. info.currentline .. ": in " .. ("%q"):format(fname)) print(" LOCALS:") local p = 1 while true do local name, val = debug.getlocal(x,p) if not name then break end print(" " .. name .. ": " .. tostringxx(val, 3)) p = p + 1 end print(" UPVALUES:") for p=1,info.nups do local name, val = debug.getupvalue(info.func,p) if not name then break end print(" " .. name .. ": " .. tostringxx(val, 3)) end x = x + 1 end end
local function myassert(b) if not b then richtraceback() error("assertion failed") end end 
--
local unpack = table.unpack or unpack
--
local H, W = read.nn()
local Ch, Cw = read.nn()
local Dh, Dw = read.nnl()
local S = {}
for i=1,H do
    S[i] = read.l():totable()
end
local function isopen(h, w)
    return S[h] and S[h][w] == '.'
end

local function make_deque()
    local a = {}
    -- elements exist at a[i] where left < i < right
    local left = 0
    local right = 1
    local function count()
        return right - left - 1
    end
    local function push_left(x)
        a[left] = x
        left = left - 1
        return x
    end
    local function pop_left()
        left = left + 1
        local x = a[left]
        a[left] = nil
        return x
    end
    local function push_right(x)
        a[right] = x
        right = right + 1
        return x
    end
    local function pop_right()
        right = right - 1
        local x = a[right]
        a[right] = nil
        return x
    end
    return count, push_left, pop_left, push_right, pop_right, a
end
local count, push_left, pop_left, push_right, pop_right = make_deque()

local from_src = array(2)
local neigh = {}
for i=-2,2 do
    for j=-2,2 do
        if i == 0 and j == 0 then
        elseif math.abs(i) + math.abs(j) == 1 then
        else
            table.insert(neigh, {i,j})
        end
    end
end

push_left({Ch, Cw, 0})
from_src[Ch][Cw] = 0
while count() > 0 do
    --print(tostringxx(a))
    local sh, sw, cur_cost = unpack(pop_left())
    -- LRDU
    local dh, dw = -1, 0
    for _=1,4 do
        dh, dw = dw, -dh -- rotate pi/2
        local th, tw = sh+dh, sw+dw
        if not isopen(th, tw) then
            goto next
        end
        if not from_src[th][tw] or from_src[th][tw] > cur_cost then
            from_src[th][tw] = cur_cost
            push_left({th, tw, cur_cost})
        end
        ::next::
    end
    cur_cost = cur_cost + 1
    for _,dhdw in ipairs(neigh) do
        dh, dw = unpack(dhdw)
        local th, tw = sh+dh, sw+dw
        if not isopen(th, tw) then
            goto next
        end
        if not from_src[th][tw] or from_src[th][tw] > cur_cost then
            from_src[th][tw] = cur_cost
            push_right({th, tw, cur_cost})
        end
        ::next::
    end
end
print(from_src[Dh][Dw] or -1)

Measured memory_bytes: 38304