Problem:
Score : 400 points

Problem Statement

A maze is composed of a grid of H \times W squares - H vertical, W horizontal.

The square at the i-th row from the top and the j-th column from the left - (i,j) - is a wall if S_{ij} is # and a road if S_{ij} is ..

There is a magician in (C_h,C_w). He can do the following two kinds of moves:

Move A: Walk to a road square that is vertically or horizontally adjacent to the square he is currently in.

Move B: Use magic to warp himself to a road square in the 5\times 5 area centered at the square he is currently in.

In either case, he cannot go out of the maze.

At least how many times does he need to use the magic to reach (D_h, D_w)?

Constraints

1 \leq H,W \leq 10^3

1 \leq C_h,D_h \leq H

1 \leq C_w,D_w \leq W

S_{ij} is # or ..

S_{C_h C_w} and S_{D_h D_w} are ..

(C_h,C_w) \neq (D_h,D_w)

Input

Input is given from Standard Input in the following format:

H W
C_h C_w
D_h D_w
S_{11}\ldots S_{1W}
\vdots
S_{H1}\ldots S_{HW}

Output

Print the minimum number of times the magician needs to use the magic. If he cannot reach (D_h,D_w), print -1 instead.

Sample Input 1

4 4
1 1
4 4
..#.
..#.
.#..
.#..

Sample Output 1

1

For example, by walking to (2,2) and then using the magic to travel to (4,4), just one use of magic is enough.

Note that he cannot walk diagonally.

Sample Input 2

4 4
1 4
4 1
.##.
####
####
.##.

Sample Output 2

-1

He cannot move from there.

Sample Input 3

4 4
2 2
3 3
....
....
....
....

Sample Output 3

0

No use of magic is needed.

Sample Input 4

4 5
1 2
2 5
#.###
####.
#..##
#..##

Sample Output 4

2

Solution in Lua (LuaJIT 2.1.0) (judge verdict: Accepted)

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)