jiahuimbzuai/CoQuIR huggingface dataset:
//  [typescript]
function main(input: string) {
	const i = input.split("\n");
	const n = parseInt(i[0], 10);
	const s = i.splice(1, n); 
	//console.log(s);

	const pollDictionary: { [key: string]: number } = {};
	let maxNum = 0;
	let maxNumPoll = "";

	for (let i = 0; i < s.length; i++) {
		const pollName = s[ i ];
		let pollNameCount = pollDictionary[ pollName ] == null ? 1 : pollDictionary[ pollName ] + 1;
		pollDictionary[ pollName ] = pollNameCount;
		
		if ( maxNum > pollNameCount ) {
			continue;
		}
		
		maxNum = pollNameCount;
		maxNumPoll = pollName;
	}
	
	//console.log( maxNum ); 
	console.log(maxNumPoll); 

}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));

//const input:string =　"7¥nbeat¥nvet¥nbeet¥nbed¥nvet¥nbet¥nbeet";
//main(input);
//  [typescript]
const main = (input: string) => {
  const S = input.trim().slice(2).split("\n")
  const countMap = new Map()
  let maxCount = 0

  S.forEach(s => {
    if (!countMap.has(s)) {
      countMap.set(s, 1);
    } else {
      countMap.set(s, countMap.get(s) + 1)
    }
    maxCount = Math.max(countMap.get(s), maxCount)
  })

  const answer = Array.from(countMap).filter(entry => entry[1] === maxCount).map(entry => entry[0]).sort()

  console.log(answer.join("\n"))
}

main(require('fs').readFileSync('/dev/stdin', 'utf8'));
//  [typescript]
const main = (input) => {
  const lines = input.trim().split("\n");
  const N = parseInt(lines[0]);
  const countMap = new Map();

  let maxCount = 0;
  lines.slice(1).forEach(S => {
    if (!countMap.has(S)) {
      countMap.set(S, 1);
    } else {
      countMap.set(S, countMap.get(S) + 1)
    }
    maxCount = Math.max(countMap.get(S), maxCount);
  });

  const answer = Array.from(countMap).filter(entry => entry[1] === maxCount).map(entry => entry[0]).sort();
  console.log(answer.join('\n'));
//  [python]
from queue import PriorityQueue as pq
import sys


mod = 10**9 + 7
input = sys.stdin.readline

delta_u = [(1, 0), (0, 1), (-1, 0), (0, -1)]
delta2_u = [(-1, -1), (-1, 1), (1, -1), (1, 1), (-2, -2), (-2, -1), (-2, 0), (-2, 1), (-2, 2), (-1, -2), (-1, 2), (0, -2), (0, 2), (1, -2), (1, 2), (2, -2), (2, -1), (2, 0), (2, 1), (2, 2)]


def main():
    #
    H, W = map(int, input().strip().split())
    Ch, Cw = map(lambda x: int(x) - 1 + 2, input().strip().split())
    Dh, Dw = map(lambda x: int(x) - 1 + 2, input().strip().split())
    GRID = []
    ANS = []
    for i in range(H + 4):
        ANS.append([mod for _ in range(W + 4)])

    GRID.append("#" * (W + 4))
    GRID.append("#" * (W + 4))
    for i in range(H):
        S = "##" + input().strip() + "##"
        GRID.append(S)
    GRID.append("#" * (W + 4))
    GRID.append("#" * (W + 4))

    # eprint('GRID ',end=':\n')
    # pprint.pprint(GRID)
    # eprint('ANS ',end=':\n')
    # pprint.pprint(ANS)

    #
    PQ = pq()
    PQ.put((0, Ch, Cw))
    while not(PQ.empty()):
        distance, Uh, Uw = PQ.get()
        distance = -distance

        # ANS[Uh][Uw] の 「スコア」 の 「更新」
        if distance >= ANS[Uh][Uw]:
            continue
        ANS[Uh][Uw] = distance

        #
        for delta_h, delta_w in delta_u:
            new_distance = distance
            new_Uh = Uh + delta_h
            new_Uw = Uw + delta_w
            if GRID[new_Uh][new_Uw] == "#":    #
                continue
            if new_distance >= ANS[new_Uh][new_Uw]:  # 「新しい距離」 が，今までに記録していたその座標における「古い距離」 よりも大きくなってしまう場合，その新しい地点はキューに追加しない()
                continue
            PQ.put((-new_distance, new_Uh, new_Uw))

        for delta_h, delta_w in delta2_u:
            new_distance = distance + 1
            new_Uh = Uh + delta_h
            new_Uw = Uw + delta_w
            if GRID[new_Uh][new_Uw] == "#":    #
                continue
            if new_distance >= ANS[new_Uh][new_Uw]:  # 「新しい距離」 が，今までに記録していたその座標における「古い距離」 よりも大きくなってしまう場合，その新しい地点はキューに追加しない()
                continue
            PQ.put((-new_distance, new_Uh, new_Uw))

    if ANS[Dh][Dw] != sys.maxsize:
        print(ANS[Dh][Dw])
    else:
        print(-1)


if __name__ == '__main__':
    main()
//  [python]
import numpy as np
H , W  = (int(d) for d in input().split())
Ch, Cw = (int(d)-1 for d in input().split())
Dh, Dw = (int(d)-1 for d in input().split())

M = np.array(
    [
        [True if d == "." else False for d in input()] for j in range(H)
    ]
)

move1 = [[-1,0], [1,0], [0,-1], [0,1]]
move2 = [
    [-2,-2], [-2,-1], [-2,0], [-2,1], [-2,2],
    [-1,-2], [-1,-1], [-1,1], [-1,2],
    [0,-2], [0,2],
    [1,-2], [1,-1], [1,1], [1,2],
    [2,-2], [2,-1], [2,0], [2,1], [2,2],
]

seen = set()
dist = np.ones([H, W], dtype=int) * 1000000
Q = [(Ch, Cw)]
seen.update(Q)
dist[Ch, Cw] = 0

while len(Q) > 0:
    P = Q.pop()
    for i in range(4):
        a = P[0]+move1[i][0]
        b = P[1]+move1[i][1]
        if a >= 0 and a < H and b >=0 and b < W and M[a, b]:
            dist[a, b] = min(dist[P], dist[a,b])
            if not (a, b) in seen:
                seen.update([(a, b)])
                Q.append((a, b))
    for i in range(20):
        a = P[0]+move2[i][0]
        b = P[1]+move2[i][1]
        if a >= 0 and a < H and b >=0 and b < W and M[a, b]:
            dist[a, b] = min(dist[P] + 1, dist[a, b])
            if not (a, b) in seen:
                seen.update([(a, b)])
                Q.append((a, b))

D = dist[Dh, Dw]
if D == 1000000:
    print(-1)
else:
    print(D)
//  [java]

import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;

/**
 * Created by enpingkuang on 2020/9/11 11:30 下午
 */
public class Main {

    static class Node{
        int i;
        int j;
        int value;

        Node(int i,int j,int value){
            this.i = i;
            this.j =j;
            this.value =value;
        }
    }

    private static int[][] dir = {{-1,0},{1,0},{0,-1},{0,1}};

    private static int vis[][] = new int[1003][1003];

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int h = scanner.nextInt();
        int w = scanner.nextInt();
        int s = scanner.nextInt();
        int e= scanner.nextInt();
        int ts = scanner.nextInt();
        int te = scanner.nextInt();
        String[] map = new String[h+1];
        for(int i=1;i<=h;i++){
            map[i] =scanner.next();
        }
        for(int i = 1;i<=h;i++){
            for(int j = 1;j<=w;j++){
                vis[i][j] = 100000000;
            }
        }
        vis[s][e] = 0;
        Deque<Node> deque = new LinkedList<>();
        deque.add(new Node(s,e,0));
        while(!deque.isEmpty()){
            Node node = deque.pollFirst();
            int now_i = node.i;
            int now_j = node.j;
            int now_value = node.value;
            for(int i = 0;i<4;i++){
                int tmp_i = dir[i][0] + now_i;
                int tmp_j = dir[i][1] + now_j;
                if(tmp_i <=0 || tmp_i > h || tmp_j <=0 || tmp_j > w)continue;
                if(vis[tmp_i][tmp_j] > now_value  && map[i].charAt(tmp_j-1) != '#') {
                    deque.addFirst(new Node(tmp_i, tmp_j, now_value));
                    vis[tmp_i][tmp_j] = now_value;
                }
            }
            for(int i = now_i-2;i<=now_i+2;i++){
                if(i <=0 || i > h)continue;
                for(int j = now_j-2;j<=now_j+2;j++){
                    if(j <=0 || j > w)continue;
                    if(vis[i][j] > now_value+1 && map[i].charAt(j-1) != '#') {
                        deque.addLast(new Node(i, j, now_value+1));
                        vis[i][j] = now_value+1;
                    }
                }
            }
        }
        System.out.println(vis[ts][te] == 100000000?-1:vis[ts][te]);
    }
}
//  [java]

import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;

/**
 * Created by enpingkuang on 2020/9/11 11:30 下午
 */
public class Main {

    static class Node{
        int i;
        int j;
        int value;

        Node(int i,int j,int value){
            this.i = i;
            this.j =j;
            this.value =value;
        }
    }

    private static boolean vis[][] = new boolean[1003][1003];

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int h = scanner.nextInt();
        int w = scanner.nextInt();
        int s = scanner.nextInt();
        int e= scanner.nextInt();
        int ts = scanner.nextInt();
        int te = scanner.nextInt();
        String[] map = new String[h+1];
        for(int i=1;i<=h;i++){
            map[i] =scanner.next();
        }
        Deque<Node> deque = new LinkedList<>();
        deque.add(new Node(s,e,0));
        vis[s][e] = true;
        int ans = -1;
        while(!deque.isEmpty()){
            Node node = deque.pollFirst();
            int now_i = node.i;
            int now_j = node.j;
            int now_value = node.value;
            if(now_i == ts && now_j == te){
                if(ans != -1) {
                    ans = Math.min(ans, now_value);
                }else {
                    ans = now_value;
                }
            }
            for(int i = now_i-1;i<=now_i+1;i++){
                if(i <=0 || i > h)continue;
                for(int j = now_j-1;j<=now_j+1;j++){
                    if(j <=0 || j > w)continue;
                    if(!vis[i][j] && map[i].charAt(j-1) != '#') {
                        deque.addFirst(new Node(i, j, now_value));
                        vis[i][j] = true;
                    }
                }
            }
            for(int i = now_i-2;i<=now_i+2;i+=2){
                if(i <=0 || i > h)continue;
                for(int j = now_j-2;j<=now_j+2;j+=2){
                    if(j <=0 || j > w)continue;
                    if(!vis[i][j] && map[i].charAt(j-1) != '#') {
                        deque.addLast(new Node(i, j, now_value+1));
                        vis[i][j] = true;
                    }
                }
            }
        }
        System.out.println(ans);
    }
}
//  [java]

import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;

/**
 * Created by enpingkuang on 2020/9/11 11:30 下午
 */
public class Main {

    static class Node{
        int i;
        int j;
        int value;

        Node(int i,int j,int value){
            this.i = i;
            this.j =j;
            this.value =value;
        }
    }

    private static boolean vis[][] = new boolean[1003][1003];

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int h = scanner.nextInt();
        int w = scanner.nextInt();
        int s = scanner.nextInt();
        int e= scanner.nextInt();
        int ts = scanner.nextInt();
        int te = scanner.nextInt();
        String[] map = new String[h+1];
        for(int i=1;i<=h;i++){
            map[i] =scanner.next();
        }
        Deque<Node> deque = new LinkedList<>();
        deque.add(new Node(s,e,0));
        int ans = -1;
        while(!deque.isEmpty()){
            Node node = deque.pollFirst();
            int now_i = node.i;
            int now_j = node.j;
            int now_value = node.value;
            if(now_i == ts && now_j == te){
                if(ans != -1) {
                    ans = Math.min(ans, now_value);
                }else {
                    ans = now_value;
                }
            }
            for(int i = now_i-1;i<=now_i+1;i++){
                if(i <=0 || i > h)continue;
                for(int j = now_j-1;j<=now_j+1;j++){
                    if(j <=0 || j > w)continue;
                    if(!vis[i][j] && map[i].charAt(j-1) != '#') {
                        deque.addFirst(new Node(i, j, now_value));
                        vis[i][j] = true;
                    }
                }
            }
            for(int i = now_i-2;i<=now_i+2;i++){
                if(i <=0 || i > h)continue;
                for(int j = now_j-2;j<=now_j+2;j++){
                    if(j <=0 || j > w)continue;
                    if(!vis[i][j] && map[i].charAt(j-1) != '#') {
                        deque.addLast(new Node(i, j, now_value+1));
                        vis[i][j] = true;
                    }
                }
            }
        }
        System.out.println(ans);
    }
}
//  [cpp]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const long long INF = 1e15;



int main(){
    ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

    int h,w;
    cin >> h >> w;

    int sx,sy,gx,gy;
    cin >> sy >> sx >> gy >> gx;
    sx--;sy--;gx--;gy--;

    pair<int,int> s = make_pair(sx,sy), g = make_pair(gx,gy); 
    string sur[h];

    for(int i = 0; i < h; i++) cin >> sur[i];

    auto inout = [&](int x,int y){
        if(0 <= x && x < w && 0 <= y && y < h) return true;
        else return false;
    };

    queue<pair<int,int>> p,q;

    int dx[4] = {0,0,1,-1}, dy[4] = {1,-1,0,0};

    p.push(s);

    int can = 0;

    while(!p.empty()){
        while(!p.empty()){
            pair<int,int> now = p.front();
            p.pop();
            q.push(now);
            for(int i = 0; i < 4; i++){
                pair<int,int> nxt = make_pair(now.first+dx[i],now.second+dy[i]);
                if(0 <= nxt.first && nxt.first < w && 0 <= nxt.second && nxt.second < h){
                    if(sur[nxt.second][nxt.first] == '.'){
                        if(nxt == g){
                            cout << can << endl;
                            return 0;
                        }
                        p.push(nxt);
                        sur[nxt.second][nxt.first] = '#';
                    }
                }
            }
        }
        can++;
        while(!q.empty()){
            pair<int,int> now = q.front();
            q.pop();
            for(int i = -2; i < 3; i++){
                for(int j = -2; j < 3; j++){
                    pair<int,int> nxt = make_pair(now.first+i,now.second+j);
                    if(0 <= nxt.first && nxt.first < w && 0 <= nxt.second && nxt.second < h){
                        if(sur[nxt.second][nxt.first] == '.'){
                            p.push(nxt);
                            sur[nxt.second][nxt.first] = '#';
                            if(nxt == g){
                                cout << can << endl;
                                return 0;
                            }
                        }
                    }
                }
            }
        }
    }

    cout << -1 << endl;

    return 0;
}
//  [cpp]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const long long INF = 1e15;



int main(){
    ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

    int h,w;
    cin >> h >> w;

    int sx,sy,gx,gy;
    cin >> sy >> sx >> gy >> gx;
    sx--;sy--;gx--;gy--;

    pair<int,int> s = make_pair(sx,sy), g = make_pair(gx,gy); 
    string sur[h];

    for(int i = 0; i < h; i++) cin >> sur[i];

    queue<pair<int,int>> p,q;

    int dx[4] = {0,0,1,-1}, dy[4] = {1,-1,0,0};

    p.push(s);

    int can = 0;

    while(!p.empty()){
        while(!p.empty()){
            pair<int,int> now = p.front();
            p.pop();
            q.push(now);
            for(int i = 0; i < 4; i++){
                pair<int,int> nxt = make_pair(now.first+dx[i],now.second+dy[i]);
                if(0 <= nxt.first && nxt.first < w && 0 <= nxt.second && nxt.second < h){
                    if(sur[nxt.second][nxt.first] == '.'){
                        if(nxt == g){
                            cout << can << endl;
                            return 0;
                        }
                        p.push(nxt);
                        sur[nxt.second][nxt.first] = '#';
                    }
                }
            }
        }
        can++;
        while(!q.empty()){
            pair<int,int> now = q.front();
            q.pop();
            for(int i = -2; i < 3; i++){
                for(int j = -2; j < 3; j++){
                    pair<int,int> nxt = make_pair(now.first+i,now.second+j);
                    if(0 <= nxt.first && nxt.first < w && 0 <= nxt.second && nxt.second < h){
                        if(sur[nxt.second][nxt.first] == '.'){
                            p.push(nxt);
                            sur[nxt.second][nxt.first] = '#';
                            if(nxt == g){
                                cout << can << endl;
                                return 0;
                            }
                        }
                    }
                }
            }
        }
    }

    cout << -1 << endl;

    return 0;
}
//  [cpp]
#include<bits/stdc++.h>
using namespace std;

int h,w;
int ch,cw;
int dh,dw;
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};

//スタートから見て何番目の領域かを記録
void dfs(vector<string> G, vector< vector<int> > &visited, int nowx, int nowy, int loop){
    visited[nowy][nowx] = loop;
    //cout<<nowx<<" "<<nowy<<" "<<loop<<endl;
    //ループなしで行けるところ
    for(int i=0;i<4;i++){
        int nextx = nowx+dx[i];
        int nexty = nowy+dy[i];
        if(nextx>=0 && nextx<w && nexty>=0 && nexty<h && G[nexty][nextx]!='#' && visited[nexty][nextx]==INT_MAX){
            dfs(G, visited,nextx,nexty,visited[nowy][nowx]);
        } 
    }
    //ループで行けるところ
    for(int y=-2;y<=2;y++){
        for(int x=-2;x<=2;x++){
            if((x==0 && y==0) || (x==0 && y==1) || (x==0 && y==-1) || (x==1 && y==0) || (x==-1 && y==0)) continue;
            int nextx = nowx+x;
            int nexty = nowy+y;
            if(nextx>=0 && nextx<w && nexty>=0 && nexty<h && G[nexty][nextx]!='#' && visited[nexty][nextx]>loop+1){
                dfs(G,visited,nextx,nexty, loop+1);
            }
        }
    }
    return;
}

int main(){
    cin>>h>>w;
    cin>>ch>>cw;
    ch--; cw--;
    cin>>dh>>dw;
    dh--; dw--;
    vector<string> G;
    //最小で何回のループでこれるか、来れないならINF
    vector< vector<int> > visited(h, vector<int>(w,INT_MAX));
    for(int i=0;i<h;i++){
        string s;
        cin>>s;
        G.push_back(s);
    }
    dfs(G,visited,cw,ch,0);
    if(visited[dh][dw]==INT_MAX) cout<<-1<<endl;
    else cout<<visited[dh][dw]<<endl;
    return 0;

}
//  [cpp]
#include<bits/stdc++.h>
using namespace std;

int h,w;
int ch,cw;
int dh,dw;
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};

//スタートから見て何番目の領域かを記録
void dfs(vector<string> G, vector< vector<int> > &visited, int nowx, int nowy, int loop){
    visited[nowy][nowx] = loop;
    cout<<nowx<<" "<<nowy<<" "<<loop<<endl;
    if(nowy==dh && nowx==dw) return;
    //ループなしで行けるところ
    for(int i=0;i<4;i++){
        int nextx = nowx+dx[i];
        int nexty = nowy+dy[i];
        if(nextx>=0 && nextx<w && nexty>=0 && nexty<h && G[nexty][nextx]!='#' && visited[nexty][nextx]==INT_MAX){
            dfs(G, visited,nextx,nexty,visited[nowy][nowx]);
        } 
    }
    //ループで行けるところ
    for(int y=-2;y<=2;y++){
        for(int x=-2;x<=2;x++){
            if((x==0 && y==0) || (x==0 && y==1) || (x==0 && y==-1) || (x==1 && y==0) || (x==-1 && y==0)) continue;
            int nextx = nowx+x;
            int nexty = nowy+y;
            if(nextx>=0 && nextx<w && nexty>=0 && nexty<h && G[nexty][nextx]!='#' && visited[nexty][nextx]==INT_MAX){
                dfs(G,visited,nextx,nexty, min(loop+1,visited[nexty][nextx]));
            }
        }
    }
    return;
}

int main(){
    cin>>h>>w;
    cin>>ch>>cw;
    ch--; cw--;
    cin>>dh>>dw;
    dh--; dw--;
    vector<string> G;
    //最小で何回のループでこれるか、来れないならINF
    vector< vector<int> > visited(h, vector<int>(w,INT_MAX));
    for(int i=0;i<h;i++){
        string s;
        cin>>s;
        G.push_back(s);
    }
    dfs(G,visited,cw,ch,0);
    if(visited[dh][dw]==INT_MAX) cout<<-1<<endl;
    else cout<<visited[dh][dw]<<endl;
    return 0;

}
//  [c]
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define rep(i,N) for(int i=0;i<(int)N;i++)
#pragma GCC optimize("O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
static inline void PUT(char c)
{
  static char buf[1<<15],*ptr=buf;
  if(ptr==buf+strlen(buf)||c==0){fwrite(buf,1,ptr-buf,stdout),ptr=buf;}*ptr++=c;
}
static inline int IN(void)
{
  int x=0,f=0,c=getchar();while(c<48||c>57){f^=c==45,c=getchar();}
  while(c>47&&c<58){x=x*10+c-48,c=getchar();}return f?-x:x;
}
static inline void OUT(int a)
{
  if(a<0)PUT('-'),a=-a;
  int d[40],i=0;do{d[i++]=a%10;}while(a/=10);
  while(i--){PUT(d[i]+48);}PUT('\n');
}
const int qsz=1e6;int qLen,qHead,Q[1000000];
static inline void PUSH(int n){Q[(qHead+qLen)%qsz]=n;qLen++;}
static inline int POP(void){int q=Q[qHead];qLen--;qHead=(qHead+1)%qsz;return q;}
int H,W,grid[1000][1000];
const int dx[24]={0,1,0,-1,0,0,1,1,1,1,-1,-1,-1,-1,2,2,2,2,2,-2,-2,-2,-2,-2};
const int dy[24]={1,0,-1,0,2,-2,1,2,-1,-2,1,2,-1,-2,0,1,2,-1,-2,0,1,2,-1,-2};
static inline int f(int x,int y){return W*x+y;}
static inline void DFS(int x,int y)
{
  if(x>=0&&x<H&&y>=0&&y<W&&!grid[x][y])
  {
    grid[x][y]=1;PUSH(f(x,y));rep(i,4){DFS(x+dx[i],y+dy[i]);}
  }
}
int main(void)
{
  int C[2],D[2],step=0;H=IN(),W=IN(),C[0]=IN()-1,C[1]=IN()-1,D[0]=IN()-1,D[1]=IN()-1;
  rep(i,H){char str[1001];if(!scanf("%s",str)){return -1;}rep(j,W){grid[i][j]=(str[j]=='#');}}
  PUSH(f(C[0],C[1]));
  while(qLen)
  {
    int size=qLen;
    while(size--){int x=POP();DFS(x/W,x%W);}
    size=qLen;
    while(size--)
    {
      int z=POP(),x=z/W,y=z%W;
      if(x==D[0]&&y==D[1]){return OUT(step),0;}
      rep(i,20)
      {
        int nx=x+dx[4+i],ny=y+dy[4+i];
        if(nx>=0&&nx<H&&ny>=0&&ny<W&&!grid[nx][ny]){PUSH(f(nx,ny));}
      }
    }
    step++;
  }
  return puts("-1"),0;
}
//  [c]
#include <ctype.h>
#include <float.h>
#include <inttypes.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <math.h>
#ifdef __cplusplus
#include <bits/stdc++.h>
#endif
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")

#define getchar getchar_unlocked
#define putchar putchar_unlocked
int32_t nextint(void){ char c=getchar(); while(c!='-'&&(c<'0'||'9'<c)) c=getchar(); bool s=false; if(c=='-'){s=true;c=getchar();} uint32_t x=0; while('0'<=c && c<='9'){ x=x*10+c-'0'; c=getchar(); } return s?-x:x; }
int64_t nextlong(void){ char c=getchar(); while(c!='-'&&(c<'0'||'9'<c)) c=getchar(); int s=0; if(c=='-'){s=1;c=getchar();} uint64_t x=0; while('0'<=c && c<='9'){ x=x*10+c-'0'; c=getchar(); } return s?-x:x; }
uint32_t nextstr(char *s){ char c=getchar(); while(c==' '||c=='\n') c=getchar(); uint32_t len=0; while(c!=' '&&c!='\n'){ *s++=c; len++; c=getchar(); } *s='\0'; return len; }
void rsorta_d32(void *base, const int count, const int size, const int index){
	typedef int32_t rsort_t;
	rsort_t (*a)[size] = (rsort_t(*)[size])base;
	rsort_t (*b)[size] = (rsort_t(*)[size])malloc(count*size*sizeof(rsort_t));
	int c[0x100];
	for(int k=0; k<4; k++){
		memset(c, 0, sizeof(c)); for(int i=0; i<count; i++){ c[(a[i][index]>>(k<<3))&0xFF]++; } for(int i=1; i<0x100; i++) c[i]+=c[i-1]; for(int i=count-1; i>=0; i--){ int to=--c[(a[i][index]>>(k<<3))&0xFF]; for(int j=0; j<size; j++){ b[to][j]=a[i][j]; } }{rsort_t(*t)[size]=a; a=b; b=t;}
	}
	free(b);
}

char m[1000][1001];
int d[1000][1000];
int s[1000000][2];
int main(void){
	int h=nextint();
	int w=nextint();
	int ch=nextint()-1;
	int cw=nextint()-1;
	int dh=nextint()-1;
	int dw=nextint()-1;
	for(int i=0; i<h; i++){
		nextstr(m[i]);
	}
	int k=0;
	int sl=0, sr=0;
	d[ch][cw]=1;
	s[sl][0]=ch, s[sl][1]=cw, sr++;
	while(1){
		k++;
		if(sl==sr) break;
		int tl=sl;
		while(sl<sr){
			int x=s[sl][0], y=s[sl][1]; sl++;
			{int i=x-1, j=y; if(0<=i&&i<h&&0<=j&&j<w && m[i][j]=='.' && d[i][j]==0){ d[i][j]=k; s[sr][0]=i, s[sr][1]=j, sr++;}}
			{int i=x+1, j=y; if(0<=i&&i<h&&0<=j&&j<w && m[i][j]=='.' && d[i][j]==0){ d[i][j]=k; s[sr][0]=i, s[sr][1]=j, sr++;}}
			{int i=x, j=y-1; if(0<=i&&i<h&&0<=j&&j<w && m[i][j]=='.' && d[i][j]==0){ d[i][j]=k; s[sr][0]=i, s[sr][1]=j, sr++;}}
			{int i=x, j=y+1; if(0<=i&&i<h&&0<=j&&j<w && m[i][j]=='.' && d[i][j]==0){ d[i][j]=k; s[sr][0]=i, s[sr][1]=j, sr++;}}
		}
		if(d[dh][dw]!=0){
			printf("%d\n", k-1);
			return 0;
		}
		int tr=sr;
		while(tl<tr){
			int x=s[tl][0], y=s[tl][1]; tl++;
			if(d[x][y]==k){
				for(int i=x-2; i<=x+2; i++){
					for(int j=y-2; j<=y+2; j++){
						if(0<=i&&i<h&&0<=j&&j<w && m[i][j]=='.' && d[i][j]==0){
							d[i][j]=k+1;
							s[sr][0]=i, s[sr][1]=j, sr++;
						}
					}
				}
			}
		}
	}
	printf("%d\n", -1);
}
//  [c]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
typedef long long ll;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define REP(i,l,r) for(ll i=l;i<(ll)(r);i++) //ll
#define max(l,r) ((l)>(r)?l:r)
#define min(l,r) ((l)<(r)?l:r)
#define swap(l,r) {ll tp=l;l=r;r=tp;}
const ll MOD = 1000000007;
const int INF = (1<<30);
int upcmpii(const void *a, const void *b){return(*(int*)a==*(int*)b?0:(*(int*)a>*(int*)b?1:-1));}
void sort_ui(int*a, int n){qsort(a,n,sizeof(int),upcmpii);}

int H,W;
int sx,sy,gx,gy;
char s[1010][1010];
int cnt[1010][1010] = {0};
ll ans = 0;
const int dx[] = {0,0,1,-1}, dy[] = {1,-1,0,0};
int qxf = 0, qxb = 0, quex[101010101];
int qyf = 0, qyb = 0, quey[101010101];

void dfs(int cx,int cy){
    cnt[cx][cy] = ans+1;
    rep(i,4){
        int nx = cx+dx[i];
        int ny = cy+dy[i];
        if(nx >= 0 && nx < H && ny >= 0 && ny < W){
            if(cnt[nx][ny] <= 0 && s[nx][ny] == '.'){
                dfs(nx,ny);
            }
        }
    }
    rep(i,5) rep(j,5) {
        int nx = cx-2+i;
        int ny = cy-2+j;
        if(nx >= 0 && nx < H && ny >= 0 && ny < W){
            if(cnt[nx][ny] == 0 && s[nx][ny] == '.'){
                cnt[nx][ny] = -1;
                quex[qxb++] = nx;
                quey[qyb++] = ny;
            }
        }
    }
}

void solve(){
    dfs(sx,sy);
    while(cnt[gx][gy] <= 0){
        ans++;
        int m = qxb-qxf;
        int tmp = 0;
        rep(i,m){
            int nnx = quex[qxf++],nny = quey[qyf++];
            if(cnt[nnx][nny] == -1) { dfs(nnx,nny); tmp++; }
        }
        if(tmp == 0 && cnt[gx][gy] == 0){
            ans = -1;
            break;
        }
    }
}

int main(){
    scanf("%d%d", &H,&W);
    scanf("%d%d%d%d", &sx,&sy,&gx,&gy);
    sx--;sy--;gx--;gy--;
    rep(i, H) scanf("%s", s[i]);

    solve();

    printf("%lld", ans);
}
//  [c]
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
int acs(const void *a, const void *b) { 
  return *(int*)a - *(int*)b;
} /* 1,2,3,4.. */
int des(const void *a, const void *b) {
  return *(int*)b - *(int*)a;
} /* 8,7,6,5.. */
int cmp_char(const void *a, const void *b) { 
  return *(char*)a - *(char*)b;
} /* a,b,c,d.. */
int cmp_str(const void *a, const void *b) {
  return strcmp(*(const char **)a, *(const char **)b);
} /* aaa,aab.. */
#define min(a,b) (a < b ? a : b)
#define max(a,b) (a > b ? a : b)
#define rep(i, l, r) for (int i = l; i < r; i++)
#define MAX 1005
#define MOD 1000000007
#define INF 1000000009
typedef long long int lli;

typedef struct {
  int front;
  int rear;
  int data[20000000][2];
} queue;

queue que;

void initQueue(queue *p) {
  p->front = p->rear = 0;
}

bool emptyQueue(queue *p) {
  return p->front == p->rear;
}

bool fullQueue(queue *p) {
  return (p->front - 1 == p->rear) || (p->front == 0 && p->rear == 20000000 - 1);
}

void queuePop(queue *p) {
  if ( emptyQueue(p) ) {
    printf("UnderFlow\n");
    exit(1);
  } else {
    p->front++;
    if (p->front == 20000000)
      p->front = 0;
  }
}

void queuePush(queue *p, int y, int x) {
  if ( fullQueue(p) ) {
    printf("OverFlow\n");
    exit(1);
  } else {
    p->data[p->rear][0] = y;
    p->data[p->rear][1] = x;
    p->rear++;
    if ( p->rear == 20000000 )
      p->rear = 0;
  }
}


int H, W, Ch, Cw, Dh, Dw;

char S[MAX][MAX];

int main(void) {
  scanf("%d %d", &H, &W);
  scanf("%d %d", &Ch, &Cw);
  scanf("%d %d", &Dh, &Dw);

  rep(i, 0, H) scanf("%s", S[i]);

  int dist[MAX][MAX];
  rep(i, 0, MAX) rep(j, 0, MAX) dist[i][j] = INF;


  int ax[4] = {0, 1, 0, -1};
  int ay[4] = {1, 0, -1, 0};

  initQueue(&que);
  queuePush(&que, Ch-1, Cw-1);
  dist[Ch-1][Cw-1] = 0;
  while ( !emptyQueue(&que) ) {
    int y = que.data[que.front][0];
    int x = que.data[que.front][1];
    queuePop(&que);
    if ( y == Dh-1 && x == Dw-1 ) {
      printf("%d\n", dist[y][x]);
      return 0;
    }
    rep(i, 0, 4) {
      int ny = y + ay[i];
      int nx = x + ax[i];
      if ( ny < 0 || H <= ny ) continue;
      if ( nx < 0 || W <= nx ) continue;
      if ( S[ny][nx] == '#' ) continue;
      if ( dist[ny][nx] <= dist[y][x] ) continue;
      dist[ny][nx] = dist[y][x];
      queuePush(&que, ny, nx); 
    }

    rep(by, -2, 3) rep(bx, -2, 3) {
      int ny = y + by;
      int nx = x + bx;
      if ( ny < 0 || H <= ny ) continue;
      if ( nx < 0 || W <= nx ) continue;
      if ( S[ny][nx] == '#' ) continue;
      if ( dist[ny][nx] <= dist[y][x] + 1 ) continue;
      dist[ny][nx] = dist[y][x] + 1;
      queuePush(&que, ny, nx);
    }
  }
  printf("-1\n");
  return 0;
}
//  [c]
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
int acs(const void *a, const void *b) { 
  return *(int*)a - *(int*)b;
} /* 1,2,3,4.. */
int des(const void *a, const void *b) {
  return *(int*)b - *(int*)a;
} /* 8,7,6,5.. */
int cmp_char(const void *a, const void *b) { 
  return *(char*)a - *(char*)b;
} /* a,b,c,d.. */
int cmp_str(const void *a, const void *b) {
  return strcmp(*(const char **)a, *(const char **)b);
} /* aaa,aab.. */
#define min(a,b) (a < b ? a : b)
#define max(a,b) (a > b ? a : b)
#define rep(i, l, r) for (int i = l; i < r; i++)
#define MAX 1005
#define MOD 1000000007
#define INF 1000000009
typedef long long int lli;

typedef struct {
  int front;
  int rear;
  int data[20000000][2];
} queue;

queue que;

void initQueue(queue *p) {
  p->front = p->rear = 0;
}

bool emptyQueue(queue *p) {
  return p->front == p->rear;
}

bool fullQueue(queue *p) {
  return (p->front - 1 == p->rear) || (p->front == 0 && p->rear == MAX - 1);
}

void queuePop(queue *p) {
  if ( emptyQueue(p) ) {
    printf("UnderFlow\n");
    exit(1);
  } else {
    p->front++;
    if (p->front == MAX)
      p->front = 0;
  }
}

void queuePush(queue *p, int y, int x) {
  if ( fullQueue(p) ) {
    printf("OverFlow\n");
    exit(1);
  } else {
    p->data[p->rear][0] = y;
    p->data[p->rear][1] = x;
    p->rear++;
    if ( p->rear == MAX )
      p->rear = 0;
  }
}


int H, W, Ch, Cw, Dh, Dw;

char S[MAX][MAX];

int main(void) {
  scanf("%d %d", &H, &W);
  scanf("%d %d", &Ch, &Cw);
  scanf("%d %d", &Dh, &Dw);

  rep(i, 0, H) scanf("%s", S[i]);

  int dist[MAX][MAX];
  rep(i, 0, MAX) rep(j, 0, MAX) dist[i][j] = INF;


  int ax[4] = {0, 1, 0, -1};
  int ay[4] = {1, 0, -1, 0};

  initQueue(&que);
  queuePush(&que, Ch-1, Cw-1);
  dist[Ch-1][Cw-1] = 0;
  while ( !emptyQueue(&que) ) {
    int y = que.data[que.front][0];
    int x = que.data[que.front][1];
    queuePop(&que);
    if ( y == Dh-1 && x == Dw-1 ) {
      printf("%d\n", dist[y][x]);
      return 0;
    }
    rep(i, 0, 4) {
      int ny = y + ay[i];
      int nx = x + ax[i];
      if ( ny < 0 || H <= ny ) continue;
      if ( nx < 0 || W <= nx ) continue;
      if ( S[ny][nx] == '#' ) continue;
      if ( dist[ny][nx] <= dist[y][x] ) continue;
      dist[ny][nx] = dist[y][x];
      queuePush(&que, ny, nx); 
    }

    rep(by, -2, 3) rep(bx, -2, 3) {
      int ny = y + by;
      int nx = x + bx;
      if ( ny < 0 || H <= ny ) continue;
      if ( nx < 0 || W <= nx ) continue;
      if ( S[ny][nx] == '#' ) continue;
      if ( dist[ny][nx] <= dist[y][x] + 1 ) continue;
      dist[ny][nx] = dist[y][x] + 1;
      queuePush(&que, ny, nx);
    }
  }
  printf("-1\n");
  return 0;
}
//  [c]
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
int acs(const void *a, const void *b) { 
  return *(int*)a - *(int*)b;
} /* 1,2,3,4.. */
int des(const void *a, const void *b) {
  return *(int*)b - *(int*)a;
} /* 8,7,6,5.. */
int cmp_char(const void *a, const void *b) { 
  return *(char*)a - *(char*)b;
} /* a,b,c,d.. */
int cmp_str(const void *a, const void *b) {
  return strcmp(*(const char **)a, *(const char **)b);
} /* aaa,aab.. */
#define min(a,b) (a < b ? a : b)
#define max(a,b) (a > b ? a : b)
#define rep(i, l, r) for (int i = l; i < r; i++)
#define MAX 1005
#define MOD 1000000007
#define INF 1000000009
typedef long long int lli;

typedef struct {
  int front;
  int rear;
  int data[16777216][2];
} queue;

queue que;

void initQueue(queue *p) {
  p->front = p->rear = 0;
}

bool emptyQueue(queue *p) {
  return p->front == p->rear;
}

bool fullQueue(queue *p) {
  return (p->front - 1 == p->rear) || (p->front == 0 && p->rear == MAX - 1);
}

void queuePop(queue *p) {
  if ( emptyQueue(p) ) {
    printf("UnderFlow\n");
    exit(1);
  } else {
    p->front++;
    if (p->front == MAX)
      p->front = 0;
  }
}

void queuePush(queue *p, int y, int x) {
  if ( fullQueue(p) ) {
    printf("OverFlow\n");
    exit(1);
  } else {
    p->data[p->rear][0] = y;
    p->data[p->rear][1] = x;
    p->rear++;
    if ( p->rear == MAX )
      p->rear = 0;
  }
}


int H, W, Ch, Cw, Dh, Dw;

char S[MAX][MAX];

int main(void) {
  scanf("%d %d", &H, &W);
  scanf("%d %d", &Ch, &Cw);
  scanf("%d %d", &Dh, &Dw);

  rep(i, 0, H) scanf("%s", S[i]);

  int dist[MAX][MAX];
  rep(i, 0, MAX) rep(j, 0, MAX) dist[i][j] = INF;


  int ax[4] = {0, 1, 0, -1};
  int ay[4] = {1, 0, -1, 0};

  initQueue(&que);
  queuePush(&que, Ch-1, Cw-1);
  dist[Ch-1][Cw-1] = 0;
  while ( !emptyQueue(&que) ) {
    int y = que.data[que.front][0];
    int x = que.data[que.front][1];
    queuePop(&que);
    if ( y == Dh-1 && x == Dw-1 ) {
      printf("%d\n", dist[y][x]);
      return 0;
    }
    rep(i, 0, 4) {
      int ny = y + ay[i];
      int nx = x + ax[i];
      if ( ny < 0 || H <= ny ) continue;
      if ( nx < 0 || W <= nx ) continue;
      if ( S[ny][nx] == '#' ) continue;
      if ( dist[ny][nx] <= dist[y][x] ) continue;
      dist[ny][nx] = dist[y][x];
      queuePush(&que, ny, nx); 
    }

    rep(by, -2, 3) rep(bx, -2, 3) {
      int ny = y + by;
      int nx = x + bx;
      if ( ny < 0 || H <= ny ) continue;
      if ( nx < 0 || W <= nx ) continue;
      if ( S[ny][nx] == '#' ) continue;
      if ( dist[ny][nx] <= dist[y][x] + 1 ) continue;
      dist[ny][nx] = dist[y][x] + 1;
      queuePush(&que, ny, nx);
    }
  }
  printf("-1\n");
  return 0;
}
//  [javascript]
const { listenerCount } = require("process");

function main(input = "") {
    const WALL = -1, ROAD = 99999999;
    const lines = input.split("\n");
    const header = lines.slice(0, 3).map((line) => (line.split(" ").map((v) => (Number(v)))));
    const H = header[0][0], W = header[0][1];
    const Ch = header[1][0] - 1, Cw = header[1][1] - 1;
    const Dh = header[2][0] - 1, Dw = header[2][1] - 1;
    const Dest = Dh * W + Dw;
    const GRID = lines.slice(3).map((line) => (line.split("").map((v) => (v === "#" ? WALL : ROAD))))
    const MAZE = new Int32Array(Array().concat(...GRID));

    let fill = (h = 0, w = 0, v = 0, arr = []) => {
        let id = h * W + w;
        if (MAZE[id] > v) {
            MAZE[id] = v;
            arr.push(id)
            if (0 <= h - 1) fill(h - 1, w, v, arr);
            if (h + 1 < H) fill(h + 1, w, v, arr);
            if (0 <= w - 1) fill(h, w - 1, v, arr);
            if (w + 1 < W) fill(h, w + 1, v, arr);
        }
    }

    let getWarpList = (area = [0]) => {
        let set = new Set();
        area.forEach((v) => {
            let ih = 0 | v / W;
            let iw = v - ih * W;
            _warpList(ih, iw, set);
        })
        return set;
    }

    let _warpList = (h = 0, w = 0, set = new Set([0])) => {
        let v = MAZE[h * W + w];
        for (let ih = -2; ih <= 2; ih++) {
            let th = h + ih;
            if (0 <= th && th < H) {
                for (let iw = -2; iw <= 2; iw++) {
                    let tw = w + iw;
                    if (0 <= tw && tw < W) {
                        let toId = th * W + tw
                        if (MAZE[toId] > v) {
                            set.add(toId);
                        }
                    }
                }
            }
        }
    }

    let area = [];
    let ch = Ch, cw = Cw;
    let color = 1;
    fill(ch, cw, color, area);
    while (true) {
        color++;
        let lst = getWarpList(area)
        area.length = 0;
        for (const v of lst) {
            let ih = 0 | v / W;
            let iw = v - ih * W;
            fill(ih, iw, color, area);
        }
        if (area.length === 0) {
            break;
        }
    }

    return MAZE[Dest] === ROAD ? -1 : MAZE[Dest] - 1;
}


//******************************
exports.main = main;

function Main(input) {
    console.log(main(input.trim()));
}

if (process.argv[2] !== "test") {
    Main(require("fs").readFileSync("/dev/stdin", "utf8"));
}
//  [javascript]
(async () => {
    let input = '';
    for await (const chunk of process.stdin) input += chunk;
    const lines = input.split(/\n/);
    const [h, w] = lines[0].split(/\s/).map(v => +v);
    const [ch, cw] = lines[1].split(/\s/).map(v => v - 1);
    const [dh, dw] = lines[2].split(/\s/).map(v => v - 1);
    const counts = lines.slice(3, h + 3).map(line => line.split('').slice(0, w).map(c => c == '#' ? -1 : Infinity));

    let que = {0: [], 1: []};
    counts[ch][cw] = 0;
    que[0].push([ch, cw, 0]);

    const addQue = (queNumber, x, y, count) => {
        if(x < 0)return;
        if(x >= h)return;
        if(y < 0)return;
        if(y >= w)return;
        if(counts[x][y] <= count)return;
        que[queNumber].push([x, y, count]);
        counts[x][y] = count;
    }
    
    while(que[0].length || que[1].length){
        if(!que[0].length){
            que[0] = que[1];
            que[1] = [];
        }
        const [x, y, count] = que[0].pop();
        if(x == dh && y == dw)break;
        
        addQue(0, x - 1, y, count);
        addQue(0, x + 1, y, count);
        addQue(0, x, y - 1, count);
        addQue(0, x, y + 1, count);
        for(let i = -2; i <= 2; i++){
            for(let j = -2; j <= 2; j++){
                addQue(1, x + i, y + j, count + 1);
            }
        }
    }

    if(counts[dh][dw] == Infinity){
        console.log(-1);
    }else{
        console.log(counts[dh][dw]);
    }

})();
//  [javascript]
"use strict";
var input=require("fs").readFileSync("/dev/stdin","utf8");
var cin=input.split(/ |\n/),cid=0;
function next(){return +cin[cid++];}
function nextstr(){return cin[cid++];}
function nextbig(){return BigInt(cin[cid++]);}
function nexts(n,a){return a?cin.slice(cid,cid+=n):cin.slice(cid,cid+=n).map(a=>+a);}
function nextm(h,w,a){var r=[],i=0;if(a)for(;i<h;i++)r.push(cin.slice(cid,cid+=w));else for(;i<h;i++)r.push(cin.slice(cid,cid+=w).map(a=>+a));return r;}
function xArray(v){var a=arguments,l=a.length,r="Array(a["+--l+"]).fill().map(x=>{return "+v+";})";while(--l)r="Array(a["+l+"]).fill().map(x=>"+r+")";return eval(r);}

var myOut = main();
if(myOut !== undefined)console.log(String(myOut));

function main(){
  var dy = [-1,0,1,0], dx = [0,1,0,-1];
  var h = next(), w = next();
  var [sy,sx] = nexts(2);
  var [gy,gx] = nexts(2);
  sy--,sx--,gy--,gx--;
  var s = nexts(h,1);
  var map = xArray(1e9,h,w);
  map[sy][sx] = 0;
  var q1 = [sy,sx], q2 = [], d = 0;
  while(q1.length){
    while(q1.length){
      var qx = q1.pop(), qy = q1.pop();
      if(map[qy][qx] < d)continue;
      for(var i = 0; i < 4; i++){
        var nx = qx+dx[i], ny = qy+dy[i];
        if(nx < 0 || nx === w || ny < 0 || ny === h)continue;
        if(s[ny][nx] === "#")continue;
        if(map[ny][nx] <= d)continue;
        map[ny][nx] = d;
        q1.push(ny,nx);
      }
      for(var y = -2; y <= 2; y++)for(var x = -2; x <= 2; x++){
        var nx = qx+x, ny = qy+y;
        if(nx < 0 || nx >= w || ny < 0 || ny >= h)continue;
        if(s[ny][nx] === "#")continue;
        if(map[ny][nx] <= d+1)continue;
        map[ny][nx] = d+1;
        q2.push(ny,nx);
      }
    }
    d++, q1 = q2, q2 = [];
  }
  return map[gy][gx] === 1e9 ? -1 : map[gy][gx];
}
//  [javascript]
(async () => {
    let input = '';
    for await (const chunk of process.stdin) input += chunk;
    const lines = input.split(/\n/);
    const [h, w] = lines[0].split(/\s/).map(v => +v);
    const [ch, cw] = lines[1].split(/\s/).map(v => v - 1);
    const [dh, dw] = lines[2].split(/\s/).map(v => v - 1);
    const counts = lines.slice(3, h + 3).map(line => line.split('').slice(0, w).map(c => c == '#' ? -1 : Infinity));

    let que = {0: [], 1: []};
    que[0].push([ch, cw, 0]);

    const addQue = (queNumber, x, y, count) => {
        if(x < 0)return;
        if(x >= h)return;
        if(y < 0)return;
        if(y >= w)return;
        if(counts[x][y] <= count)return;
        que[queNumber].push([x, y, count]);
    }
    
    while(que[0].length || que[1].length){
        if(!que[0].length){
            que[0] = que[1];
            que[1] = [];
        }
        const [x, y, count] = que[0].pop();

        if(x < 0)continue;
        if(x >= h)continue;
        if(y < 0)continue;
        if(y >= w)continue;
        if(counts[x][y] > count){
            counts[x][y] = count;
            if(x == dh && y == dw)break;
        }else{
            continue;
        }
        
        addQue(0, x - 1, y, count);
        addQue(0, x + 1, y, count);
        addQue(0, x, y - 1, count);
        addQue(0, x, y + 1, count);
        for(let i = -2; i <= 2; i++){
            for(let j = -2; j <= 2; j++){
                addQue(1, x + i, j + i, count + 1);
            }
        }
    }

    if(counts[dh][dw] == Infinity){
        console.log(-1);
    }else{
        console.log(counts[dh][dw]);
    }

})();
//  [javascript]
(async () => {
    let input = '';
    for await (const chunk of process.stdin) input += chunk;
    const lines = input.split(/\n/);
    const [h, w] = lines[0].split(/\s/).map(v => +v);
    const [ch, cw] = lines[1].split(/\s/).map(v => v - 1);
    const [dh, dw] = lines[2].split(/\s/).map(v => v - 1);
    const counts = lines.slice(3, h + 3).map(line => line.split('').slice(0, w).map(c => c == '#' ? -1 : Infinity));

    let que = {0: [], 1: []};
    que[0].push([ch, cw, 0]);
    while(que[0].length || que[1].length){
        if(!que[0].length){
            que[0] = que[1];
            que[1] = [];
        }
        const [x, y, count] = que[0].pop();

        if(x < 0)continue;
        if(x >= h)continue;
        if(y < 0)continue;
        if(y >= w)continue;
        if(counts[x][y] > count){
            counts[x][y] = count;
            if(x == dh && y == dw)break;
        }else{
            continue;
        }
        
        que[0].push([x - 1, y, count]);
        que[0].push([x + 1, y, count]);
        que[0].push([x, y - 1, count]);
        que[0].push([x, y + 1, count]);
        for(let i = -2; i <= 2; i++){
            for(let j = -2; j <= 2; j++){
                if(counts[x + i][y + j] > count + 1){
                    que[1].push([x + i, y + j, count + 1]);
                }
            }
        }
    }

    if(counts[dh][dw] == Infinity){
        console.log(-1);
    }else{
        console.log(counts[dh][dw]);
    }

})();
//  [javascript]
(async () => {
    let input = '';
    for await (const chunk of process.stdin) input += chunk;
    const lines = input.split(/\n/);
    const [h, w] = lines[0].split(/\s/).map(v => +v);
    const [ch, cw] = lines[1].split(/\s/).map(v => v - 1);
    const [dh, dw] = lines[2].split(/\s/).map(v => v - 1);
    const counts = lines.slice(3, h + 3).map(line => line.split('').slice(0, w).map(c => c == '#' ? -1 : Infinity));

    let que = {0: [], 1: []};
    que[0].push([ch, cw, 0]);
    while(que[0].length || que[1].length){
        if(!que[0].length){
            que[0] = que[1];
            que[1] = [];
        }
        const [x, y, count] = que[0].pop();

        if(x < 0)continue;
        if(x >= h)continue;
        if(y < 0)continue;
        if(y >= w)continue;
        if(counts[x][y] > count){
            counts[x][y] = count;
            if(x == dh && y == dw)break;
        }else{
            continue;
        }
        
        que[0].push([x - 1, y, count]);
        que[0].push([x + 1, y, count]);
        que[0].push([x, y - 1, count]);
        que[0].push([x, y + 1, count]);
        for(let i = -2; i <= 2; i++){
            for(let j = -2; j <= 2; j++){
                que[1].push([x + i, y + j, count + 1]);
            }
        }
    }

    if(counts[dh][dw] == Infinity){
        console.log(-1);
    }else{
        console.log(counts[dh][dw]);
    }

})();
//  [go]
package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
)

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func main() {
	defer flush()

	H := readInt()
	W := readInt()
	Ch := readInt() - 1
	Cw := readInt() - 1
	Dh := readInt() - 1
	Dw := readInt() - 1
	S := make([]string, H)
	for i := 0; i < H; i++ {
		S[i] = readString()
	}

	t := make([][]int, H)
	for i := 0; i < H; i++ {
		t[i] = make([]int, W)
		for j := 0; j < W; j++ {
			if S[i][j] == '#' {
				t[i][j] = -1
			} else {
				t[i][j] = math.MaxInt64
			}
		}
	}

	warpCount := 0
	t[Ch][Cw] = warpCount
	q := make([][2]int, 0, 1024)
	q = append(q, [2]int{Ch, Cw})

	warpq := make([][2]int, 0, 1024)
	for len(q) != 0 {
		for len(q) != 0 {
			warpq = append(warpq, q[0])
			h, w := q[0][0], q[0][1]
			q = q[1:]
			if h-1 >= 0 && t[h-1][w] > warpCount {
				q = append(q, [2]int{h - 1, w})
				t[h-1][w] = t[h][w]
			}
			if h+1 < H && t[h+1][w] > warpCount {
				q = append(q, [2]int{h + 1, w})
				t[h+1][w] = t[h][w]
			}
			if w-1 >= 0 && t[h][w-1] > warpCount {
				q = append(q, [2]int{h, w - 1})
				t[h][w-1] = t[h][w]
			}
			if w+1 < W && t[h][w+1] > warpCount {
				q = append(q, [2]int{h, w + 1})
				t[h][w+1] = t[h][w]
			}
		}

		if t[Dh][Dw] != math.MaxInt64 {
			break
		}

		warpCount++
		for i := 0; i < len(warpq); i++ {
			h, w := warpq[i][0], warpq[i][1]
			for i := max(0, h-2); i <= min(H-1, h+2); i++ {
				for j := max(0, w-2); j <= min(W-1, w+2); j++ {
					if t[i][j] <= warpCount {
						continue
					}
					t[i][j] = warpCount
					q = append(q, [2]int{i, j})
				}
			}
		}
		warpq = warpq[:0]
	}

	if t[Dh][Dw] == math.MaxInt64 {
		println(-1)
	} else {
		println(t[Dh][Dw])
	}
}

const (
	ioBufferSize = 1 * 1024 * 1024 // 1 MB
)

var stdinScanner = func() *bufio.Scanner {
	result := bufio.NewScanner(os.Stdin)
	result.Buffer(make([]byte, ioBufferSize), ioBufferSize)
	result.Split(bufio.ScanWords)
	return result
}()

func readString() string {
	stdinScanner.Scan()
	return stdinScanner.Text()
}

func readInt() int {
	result, err := strconv.Atoi(readString())
	if err != nil {
		panic(err)
	}
	return result
}

var stdoutWriter = bufio.NewWriter(os.Stdout)

func flush() {
	stdoutWriter.Flush()
}

func println(args ...interface{}) (int, error) {
	return fmt.Fprintln(stdoutWriter, args...)
}