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 Java (OpenJDK 11.0.6) (judge verdict: Time Limit Exceeded)

import java.util.*;
import java.io.*;

class Main {

    Scanner in;
    InputStream is;
    PrintWriter out;
    String INPUT = "";
    class Dsu {

        int par[];
        int size[];
        Dsu(int n) {
            par = new int[n];
            size = new int[n];
            for (int i = 0; i < n; i++) {
                par[i] = i;
                size[i] = 1;
            }
        }

        int root(int i) {
            if (i == par[i]) {
                return i;
            }
            return par[i] = root(par[i]);
        }

        void union(int p, int q) {
            int a = root(p);
            int b = root(q);
            if (a == b) {
                return;
            }
            if (size[a] < size[b]) {
                int temp = a;
                a = b;
                b = temp;
            }
            par[b] = a;
            size[a] += size[b];
        }


    }
//----------------------------------------------------------------------------------------------------//
    int INF=Integer.MAX_VALUE;
    int mod=(int)(1e9)+7;
    int n,m,src[],des[],s,d;
    char mat[][];
    int dx[]=new int[]{1,-1,0,0};    
    int dy[]=new int[]{0,0,1,-1}; 
    Map<Integer, Integer> roots;
    Set<Integer>adj[];
    boolean vis[];
    Dsu uf;
    void graph(int n){
        adj=new HashSet[n];
        vis=new boolean[n];
        for (int i = 0; i < n; i++) {
            adj[i]=new HashSet<>();
        }
    }
    void addEdge(int u,int v){
        adj[u].add(v);
        adj[v].add(u);
    }
    
    boolean isValid(int i,int j){
        return (!(i<0||j<0||i>=n||j>=m||mat[i][j]=='#'));
    }
    
    void connectAll(int x,int y){
        int u=roots.get(uf.root(x*m+y));
        for (int i = Math.max(0, x-2); i < Math.min(n, x+3); i++) {
            for (int j = Math.max(0, y-2); j < Math.min(m,y+3); j++) {
                if(mat[i][j]=='#')continue;
                int v=roots.get(uf.root(i*m+j));
                if(u!=v)addEdge(u, v);
            }
        }
    }
    int bfs(){
        int cnt=0;
        Queue<Integer> q=new LinkedList<>();
        q.add(s);
        while(!q.isEmpty()){
            
            int nq=q.size();
            for (int i = 0; i < nq; i++) {
                int u=q.poll();
                vis[u]=true;
                if(u==d)return cnt;
                for (Integer v : adj[u]) {
                    if(!vis[v])
                        q.add(v);
                }
            }
            cnt++;
            
        }
        return -1;
    }
     void solve() throws IOException {
        int tt = 1;
        //t = ni();
        while (tt-- > 0) {
           n=ni();
           m=ni();
           mat=new char[n][m];
            src=new int[2];
            des=new int[2];
            src[0]=ni()-1;
            src[1]=ni()-1;
            des[0]=ni()-1;
            des[1]=ni()-1;
             for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    mat[i][j]=nc();
                }
            }
             uf=new Dsu(n*m);
             for (int i = 0; i < n; i++) {
                 for (int j = 0; j < m; j++){ 
                     if(mat[i][j]=='#')continue;
                     for (int k = 0; k < 4; k++) {
                         int x=i+dx[k];
                         int y=j+dy[k];
                         if(isValid(x, y)){
                             uf.union(i*m+j, x*m+y);
                         }
                     }
                 }
            }
             if(uf.root(src[0]*m+src[1])==uf.root(des[0]*m+des[1])){
                 out.println(0);
                 return;
             }
             roots = new HashMap<>();
            int idx=0;
             for (int i = 0; i < n; i++) {
                 for (int j = 0; j < m; j++) {
                     if(mat[i][j]=='#')continue;
                     int r=uf.root(i*m+j);
                     if(!roots.containsKey(r))roots.put(r, idx++);
                 }
            }
             /*for (Integer r : roots.keySet()) {
                 out.println(r+" "+roots.get(r));
            }*/
             graph(idx);
             s=roots.get(uf.root(src[0]*m+src[1]));
             d=roots.get(uf.root(des[0]*m+des[1]));
            // out.println(s+"->"+d);
             for (int i = 0; i < n; i++) {
                 for (int j = 0; j < m; j++) {
                     if(mat[i][j]=='#')continue;
                     connectAll(i, j);
                 }
            }
             /*idx=0;
             for (Set<Integer> list : adj) {
                 out.print((idx++)+"-");
                 for (Integer v : list) {
                     out.print(v+" ");
                 }
                 out.println();
            }*/
            out.println(bfs()); 
             
        }

    }
//----------------------------------------------------------------------------------------------------//

    void run() throws Exception {
        is = System.in;
        out = new PrintWriter(System.out);

        //long s = System.currentTimeMillis();
        solve();
        out.flush();
        //tr(System.currentTimeMillis() - s + "ms");
    }

    public static void main(String[] args) throws Exception {
        new Main().run();
    }

    private byte[] inbuf = new byte[1024];
    public int lenbuf = 0, ptrbuf = 0;

    private int readByte() {
        if (lenbuf == -1) {
            throw new InputMismatchException();
        }
        if (ptrbuf >= lenbuf) {
            ptrbuf = 0;
            try {
                lenbuf = is.read(inbuf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (lenbuf <= 0) {
                return -1;
            }
        }
        return inbuf[ptrbuf++];
    }

    private boolean isSpaceChar(int c) {
        return !(c >= 33 && c <= 126);
    }

    private int skip() {
        int b;
        while ((b = readByte()) != -1 && isSpaceChar(b));
        return b;
    }

    private double nd() {
        return Double.parseDouble(ns());
    }

    private char nc() {
        return (char) skip();
    }

    private String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while (!(isSpaceChar(b))) {  // when nextLine(take whole line as input wid space), (!isSpaceChar(b) || b == ' ') 
            //if(b!=' ') to remove spaces in Str when taking spaces in Str
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while (p < n && !(isSpaceChar(b))) {
            buf[p++] = (char) b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for (int i = 0; i < n; i++) {
            map[i] = ns(m);
        }
        return map;
    }

    private int[] na(int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = ni();
        }
        return a;
    }

    private int ni() {
        int num = 0, b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if (b == '-') {
            minus = true;
            b = readByte();
        }

        while (true) {
            if (b >= '0' && b <= '9') {
                num = num * 10 + (b - '0');
            } else {
                return minus ? -num : num;
            }
            b = readByte();
        }
    }
    /*private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
    
    private void tr(Object... o) {
        if (!oj) {
            System.out.println(Arrays.deepToString(o));
            
        }
    }*/

}