#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;
}