#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<ll,ll>;
const ll N=1e3+5;
// 存储网格地图:g[i][j]表示第i行第j列的格子状态('.'为可通行)
char g[N][N];
// 核心:map<坐标, 步数> 记录每个格子的最短步数(同时标记是否已访问)
map<PII,ll>s;
ll n,m; // 网格的行数n、列数m
queue<PII>q; // BFS核心队列:存储待扩展的格子坐标(保证逐层遍历,实现最短路径)
// 方向数组:上下左右四个移动方向(dx[i], dy[i])组合表示一个方向
ll dx[]={-1,1,0,0};
ll dy[]={0,0,-1,1};
ll xs,ys,xt,yt; // 起点坐标(xs,ys)、终点坐标(xt,yt)
// BFS核心函数:广度优先搜索求解最短路径
// 算法思想:逐层扩展起点的可达格子,每个格子仅访问一次,保证首次到达时的步数为最短(无权图特性)
void bfs(){
// 队列非空时,持续扩展节点(BFS的核心循环)
while(!q.empty()){
// 取出队列头部节点(当前层的第一个节点)
ll a=q.front().first,b=q.front().second;
q.pop();
// 遍历四个移动方向(上下左右)
for(ll i=0;i<4;i++){
// 计算新坐标:当前节点+方向偏移量
ll x=a+dx[i],y=b+dy[i];
// 步骤1:判断新格子是否可通行(非'.'表示障碍物/不可通行,跳过)
if(g[x][y]!='.'){
continue;
}
// 步骤2:判断新格子是否已访问(map中存在则说明已处理过,跳过,避免重复访问)
if(s.find({x,y})!=s.end()){
continue;
}
// 步骤3:记录新格子的最短步数 = 父节点步数 + 1(BFS逐层扩展,步数递增)
s[{x,y}]=s[{a,b}]+1;
// 步骤4:将新格子入队,等待扩展其相邻节点
q.push({x,y});
}
}
}
int main() {
// 优化输入输出速度:关闭cin与stdio同步,解绑cin和cout
ios::sync_with_stdio(0),cin.tie(0);
// 输入网格大小:行数n、列数m
cin>>n>>m;
// 输入起点坐标(xs,ys)、终点坐标(xt,yt)
cin>>xs>>ys>>xt>>yt;
// 输入网格地图:逐行逐列读取每个格子的状态
for(ll i=1;i<=n;i++){
for(ll j=1;j<=m;j++){
cin>>g[i][j];
}
}
// BFS初始化:起点入队,起点的最短步数为0(自身)
q.push({xs,ys});
s[{xs,ys}]=0;
// 执行BFS,遍历所有可达格子并记录步数
bfs();
// 结果判断:若终点在步数map中,说明可达,输出最短步数;否则输出-1(不可达)
if(s.find({xt,yt})!=s.end()){
cout<<s[{xt,yt}];
}
else cout<<-1;
return 0;
}