#include<bits/stdc++.h>
using namespace std;

long long di[4] = {0, -1, 0, 1};
long long dj[4] = {1, 0, -1, 0};
//(R, C)
//(i, j)
//array[][]

#define INF 1000000000000
const long long MOD = 1000000007;

// 🔴
// O(ElogE)

// pq<pair> はfirstが大きい順に出てくるのですか？
// s:= 開始ノード  v:= 頂点数  adjlist:= 隣接リスト (first:= コスト   second:= 行先)
vector<long long> dijk(long long s, long long v, vector<vector<pair<long long, long long> > > &adjlist){

    priority_queue <pair<long long, long long> > wait;
    vector<long long> result(v, INF);

    //スタート地点を追加
    result[s] = 0;
    wait.push(make_pair(0, s));

    //ダイクストラ本体
    while(!wait.empty()){    //waitが空になるまで

        long long nowpoint = wait.top().second;
        long long nowcost = -wait.top().first;
        wait.pop();

        if(result[nowpoint] < nowcost) continue;

        //今いる頂点と隣接しているすべての頂点をなめる
        for(long long i = 0; i < adjlist[nowpoint].size(); i++){

            long long nextpoint = adjlist[nowpoint][i].second;
            long long nextcost = nowcost + adjlist[nowpoint][i].first;
            //現時点より安く到達できそうであれば、結果を更新して優先度付きキューに格納
            if(result[nextpoint] > nextcost){
                result[nextpoint] = nextcost;
                wait.push(make_pair(-nextcost, nextpoint));
            }
        }
    }
    
    return result;         //結果列を返す
}

int main(){

    long long R, C, si, sj, gi, gj; cin >> R >> C >> si >> sj >> gi >> gj;
    
    vector<vector<long long> > MAP(R, vector<long long> (C));
    long long n = 0;        //頂点数
    for(long long i = 0; i < R; i++){
        for(long long j = 0; j < C; j++){
            MAP[i][j] = n;
            n++;
        }
    }

    vector<vector<pair<long long, long long> > > adj(n);

    for(long long i = 0; i < R; i++){
        for(long long j = 0; j < C; j++){

            long long now = MAP[i][j];
            
            //上下左右
            for(long long h = 0; h < 4; h++){
                long long ni = i + di[h];
                long long nj = j + dj[h];
                if(ni < 0 || R <= ni || nj < 0 || C <= nj) continue;

                long long next = MAP[ni][nj];
                adj[now].push_back({1, next});
            }

            //特殊辺
            long long next = MAP[i][0];
            if(now != next) adj[now].push_back({1, next});
            next = MAP[i][C - 1];
            if(now != next) adj[now].push_back({1, next});
            next = MAP[0][j];
            if(now != next) adj[now].push_back({1, next});
            next = MAP[R - 1][j];
            if(now != next) adj[now].push_back({1, next});                             
        }
    }

    vector<long long> result(n);
    long long S = MAP[si][sj];
    long long G = MAP[gi][gj];
    result = dijk(S, n, adj);
    //cout << result[G] << endl;
    

    //辺削除
    vector<bool> used(n, false);
    vector<long long> dp(n, 0);

    dp[S] = 1;
    used[S] = true;
    queue<long long> q;
    q.push(S);

    while(!q.empty()){
        
        long long now = q.front();
        q.pop();
        for(auto e : adj[now]){

            int next = e.second;
            if(result[next] - result[now] != 1) continue;
            dp[next] += dp[now];
            dp[next] %= MOD;
            if(!used[next]){
                q.push(next);
                used[next] = true;
            }
        }
    }

    cout << result[G] << " " << dp[G] << endl;
    return 0;
}


Measured memory_bytes: 37208