#include <iostream>
#include <cstdio>
#include <vector>
#include <complex>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <cstring>
#include <stack>
#include <cmath>
#include <iomanip>
#include <sstream>

using namespace std;

typedef long long ll;
typedef ll li;
typedef pair<int,int> PI;

#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define F first
#define S second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define SZ(a) (int)((a).size())
#define ALL(a) a.begin(),a.end()
#define FOR(it,a) for(__typeof(a.begin())it=a.begin();it!=a.end();++it)


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

int kdx1[]={-1,0,2,1};
int kdy1[]={0,2,1,-1};

int kdx2[]={-1,1,2,0};
int kdy2[]={1,2,0,-1};

int h,w;

const int INF=1<<28;

string in[100];

bool overking(PI a,PI king){
  return
    king.F<=a.F && a.F<=king.F+1 &&
    king.S<=a.S && a.S<=king.S+1;
}

bool inboard(PI a){
  if(a.F<0 || a.S<0 || a.F>=h || a.S>=w) return false;
  return in[a.F][a.S]!='*';
}

bool costvis[50][50];

int getcost(PI a,PI b,PI king){
  memset(costvis,0,sizeof(costvis));
  queue<pair<int,PI > > q;
  q.push(mp(0,a));

  /*
  cout << "getcost start "<<a.F<<' '<<a.S<<endl;
  cout << "getcost goal "<<b.F<<' '<<b.S<<endl;
  */
  
  while(!q.empty()){
    int cc=q.front().F;
    PI cv=q.front().S;
    q.pop();
    if(costvis[cv.F][cv.S]) continue;
    //cout <<"getcost "<<cv.F<<' '<<cv.S<<" cost "<<cc<<endl;
    if(b==cv) return cc;
    costvis[cv.F][cv.S]=true;
    rep(i,4){
      int nx=cv.F+dx[i];
      int ny=cv.S+dy[i];
      if(overking(mp(nx,ny),king) || !inboard(mp(nx,ny))) continue;
      q.push(mp(cc+1,mp(nx,ny)));
    }
  }

  return INF;
}

bool vis[4][50][50];


void solve(){

  vector<PI> pawn;
  PI king;
  rep(i,h) cin >> in[i];
  
  rep(i,h){
    // cout << in[i]<<endl;
    rep(j,w){
      if(in[i][j]=='.') pawn.pb(mp(i,j));
      if(in[i][j]=='X' && i+1<h && j+1<w && in[i+1][j+1]=='X') king=PI(i,j);
    }
  }

  if(king == mp(0,0)){
    cout<<0<<endl;
    return;
  }

  priority_queue<pair<PI,PI> > q; // cost,dir,pos
  
  rep(i,4){
    int cost=INF;
    PI k1=mp(king.F+kdx1[i],king.S+kdy1[i]);
    PI k2=mp(king.F+kdx2[i],king.S+kdy2[i]);    
    if(!(inboard(k1) && inboard(k2))) continue;

    cost = min(cost,getcost(pawn[0],k1,king)+getcost(pawn[1],k2,king));
    cost = min(cost,getcost(pawn[0],k2,king)+getcost(pawn[1],k1,king));
    //cout << "start "<<i<<' '<<cost<<endl;
    if(cost < INF/4){
      q.push(mp(mp(-cost,i),king));
    }
  }

  memset(vis,0,sizeof(vis));
  while(!q.empty()){
    int cc=-q.top().F.F;
    int dir=q.top().F.S;
    PI king=q.top().S;
    q.pop();
    if(vis[dir][king.F][king.S]) continue;
    vis[dir][king.F][king.S]=true;
    //cout << dir <<' ' <<king.F<< ' '<<king.S<<' '<<cc<<endl;
    if(king==mp(0,0)){
      cout<<cc<<endl;
      return;
    }
    pawn[0]=mp(king.F+kdx1[dir],king.S+kdy1[dir]);
    pawn[1]=mp(king.F+kdx2[dir],king.S+kdy2[dir]);
    rep(i,4){
      if(dir==i){
	PI nc=mp(-cc-1,(i+2)&3);
	PI pos=mp(king.F+dx[i],king.S+dy[i]);
	q.push(mp(nc,pos));
	continue;
      }
      
      int cost = INF;
      if(!(inboard(mp(king.F+kdx1[i],king.S+kdy1[i])) &&
	   inboard(mp(king.F+kdx2[i],king.S+kdy2[i])))) continue;
      PI k1=mp(king.F+kdx1[i],king.S+kdy1[i]);
      PI k2=mp(king.F+kdx2[i],king.S+kdy2[i]);
      cost = min(cost,getcost(pawn[0],k1,king)+getcost(pawn[1],k2,king));
      cost = min(cost,getcost(pawn[0],k2,king)+getcost(pawn[1],k1,king));
      if(cost>INF/4) continue;
      PI nking=mp(king.F+dx[i],king.S+dy[i]);
      q.push(mp(mp(-cost-1-cc,(i+2)&3),nking));
    }
  }

  cout << -1 << endl;

}

main(){
  while(cin>>h>>w,w) solve();
}

Measured memory_bytes: 1284