#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>

using namespace std;

typedef pair<int, int> P;

const int N = 50;
const int INF = 1 << 28;

int h, w, cost[N][N][4][4];
char pz[N][N];
int dy[8] = {-1, -1, 0, 1, 2, 2, 1, 0};
int dx[8] = {0, 1, 2, 2, 1, 0, -1, -1};
int dy2[4] = {-1, 0, 1, 0};
int dx2[4] = {0, 1, 0, -1};

void bfs(int sy, int sx, int vis[N][N]){
  fill(vis[0], vis[N], INF);
  vis[sy][sx] = 0;
  queue<P> q;
  q.push(P(sy * w + sx, 0));
  while(!q.empty()){
    P u = q.front(); q.pop();
    int uy = u.first / w;
    int ux = u.first % w;
    for(int i=0;i<4;i++){
      int ny = uy + dy2[i];
      int nx = ux + dx2[i];
      if(ny < 0 || ny >= h) continue;
      if(nx < 0 || nx >= w) continue;
      if(pz[ny][nx] == '*') continue;
      if(vis[ny][nx] != INF) continue;
      vis[ny][nx] = u.second + 1;
      q.push(P(ny * w + nx, u.second + 1));
    }
  }
}

int calc(int y, int x, P f1, P f2, int t){
  if(pz[y][x] == '*' || pz[y+1][x] == '*' || pz[y][x+1] == '*' || pz[y+1][x+1] == '*') return INF;
  int ny1 = y + dy[t*2];
  int nx1 = x + dx[t*2];
  int ny2 = y + dy[t*2+1];
  int nx2 = x + dx[t*2+1];
  if(min(ny1, ny2) < 0 || max(ny1, ny2) >= h) return INF;
  if(min(nx1, nx2) < 0 || max(nx1, nx2) >= w) return INF;
  if(pz[ny1][nx1] == '*' || pz[ny2][nx2] == '*') return INF;
  pz[y][x] = pz[y+1][x] = pz[y][x+1] = pz[y+1][x+1] = '*';
  int vis[2][N][N];
  bfs(f1.first, f1.second, vis[0]);
  bfs(f2.first, f2.second, vis[1]);
  pz[y][x] = pz[y+1][x] = pz[y][x+1] = pz[y+1][x+1] = 'X';
  return min(vis[0][ny1][nx1] + vis[1][ny2][nx2], vis[0][ny2][nx2] + vis[1][ny1][nx1]);
}

class S{
public:
  P p;
  int fd, c;
  S(){}
  S(P p, int fd, int c) : p(p), fd(fd), c(c) {}
  bool operator < (const S& s) const { return c > s.c; }
};

int solve(P s, P p1, P p2){
  int dist[N][N][4];
  priority_queue<S> que;
  fill(dist[0][0], dist[N][0], INF);
  for(int i=0;i<4;i++){
    int ny = s.first + dy2[i];
    int nx = s.second + dx2[i];
    if(ny < 0 || ny+1 >= h) continue;
    if(nx < 0 || nx+1 >= w) continue;
    if(pz[ny][nx] == '*' || pz[ny+1][nx] == '*' || pz[ny][nx+1] == '*' || pz[ny+1][nx+1] == '*') continue;
    int nfd = (1 - i / 2) * 2 + i % 2;
    dist[s.first][s.second][i] = calc(s.first, s.second, p1, p2, i);
    que.push(S(P(s.first, s.second), i, dist[s.first][s.second][i]));
  }
  while(!que.empty()){
    S u = que.top(); que.pop();
    int uy = u.p.first;
    int ux = u.p.second;
    if(dist[uy][ux][u.fd] < u.c) continue;
    for(int i=0;i<4;i++){
      int ny = uy + dy2[i];
      int nx = ux + dx2[i];
      if(ny < 0 || ny+1 >= h) continue;
      if(nx < 0 || nx+1 >= w) continue;
      if(pz[ny][nx] == '*' || pz[ny+1][nx] == '*' || pz[ny][nx+1] == '*' || pz[ny+1][nx+1] == '*') continue;
      int nc = cost[uy][ux][u.fd][i];
      int nfd = (1 - i / 2) * 2 + i % 2;
      if(dist[ny][nx][nfd] > dist[uy][ux][u.fd] + nc + 1){
        dist[ny][nx][nfd] = dist[uy][ux][u.fd] + nc + 1;
        que.push(S(P(ny, nx), nfd, dist[ny][nx][nfd]));
      }
    }
  }
  int res = INF;
  for(int i=0;i<4;i++) res = min(res, dist[0][0][i]);
  return res == INF ? -1 : res;
}

main(){
  while(cin >> h >> w && (h|w)){
    P s, p1, p2;
    s = p1 = p2 = P(-1, -1);
    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
        cin >> pz[i][j];
        if(pz[i][j] == 'X' && s.first == -1) s = P(i, j);
        if(pz[i][j] == '.'){
          if(p1.first == -1) p1 = P(i, j);
          else if(p2.first == -1) p2 = P(i, j);
        }
      }
    }
    if(pz[0][0] == 'X'){
      cout << 0 << endl;
      continue;
    }
    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
        for(int f=0;f<4;f++){
          for(int t=0;t<4;t++){
            cost[i][j][f][t] = calc(i, j, P(i+dy[f*2], j+dx[f*2]), P(i+dy[f*2+1], j+dx[f*2+1]), t);
          }
        }
      }
    }
    cout << solve(s, p1, p2) << endl;
  }
}

Measured memory_bytes: 1384