#include <iostream>
#include <algorithm>
#include <limits>
#include <queue>
#include <deque>
#include <vector>

#define frs first
#define scn second
#define mpr make_pair
#define pbk push_back
using namespace std;

const int kInf = numeric_limits< int >::max() / 10;
typedef pair< int, int > Pr;
typedef pair< int, pair< Pr, int > > PQNode;
typedef priority_queue< PQNode, vector< PQNode >, greater< PQNode > > PQue;

const int kNxt1[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};

const int kNxt2[4][2][2] = {
  {{-1, 0}, {-1, 1}},
  {{0, 2}, {1, 2}},
  {{2, 0}, {2, 1}},
  {{0, -1}, {1, -1}}
};

int H, W;
char plt[52][52];
Pr king, fc1, fc2;
int f[52][52][4];

void read();
void soups_on();
void yee_haw();
int sugar_cube(Pr, Pr, Pr, Pr, Pr);
int bfs(Pr, Pr);

inline bool is_valid(Pr p) {
  for (int i = 0; i <= 1; ++i)
    for (int j = 0; j <= 1; ++j)
      if (plt[p.frs + i][p.scn + j] == '*')
        return false;
  return true;
}

int main() {
  while (cin >> H >> W, H + W)
    read(), soups_on();

  return 0;
}

void read() {
  king.frs = king.scn = -1;
  fc1.frs = fc1.scn = fc2.frs = fc2.scn = -1;
  fill(&plt[0][0], &plt[52][0], '*');
  for (int i = 1; i <= H; ++i)
    for (int j = 1; j <= W; ++j) {
      cin >> plt[i][j];
      if (plt[i][j] == 'X') {
        plt[i][j] = 'o';
        if (king.frs == -1)
          king.frs = i, king.scn = j;
      }
      else if (plt[i][j] == '.') {
        plt[i][j] = 'o';
        if (fc1.frs == -1)
          fc1.frs = i, fc1.scn = j;
        else
          fc2.frs = i, fc2.scn = j;
      }
    }
}

void soups_on() {
  if (king.frs == 1 && king.scn == 1) {
    cout << "0\n";
    return;
  }

  fill(&f[0][0][0], &f[52][0][0], kInf);
  yee_haw();

  PQue pq;
  PQNode tp;
  Pr uk, vk, s1, s2, g1, g2;
  int ud, vd, cst, res, ln;

  for (int i = 0; i < 4; ++i)
    if ((cst = f[king.frs][king.scn][i]) < kInf)
      pq.push(mpr(cst, mpr(king, i)));

  res = kInf;
  while (!pq.empty()) {
    tp = pq.top(), pq.pop();
    cst = tp.frs, uk = tp.scn.frs, ud = tp.scn.scn;

    if (cst > f[uk.frs][uk.scn][ud])  continue;
    if (uk.frs == 1 && uk.scn == 1) {
      res = cst;
      break;
    }

    // move king piece
    vk = uk, vk.frs += kNxt1[ud][0], vk.scn += kNxt1[ud][1];
    vd = (ud + 2) % 4;
    if (is_valid(vk) && f[vk.frs][vk.scn][vd] > cst + 1) {
      f[vk.frs][vk.scn][vd] = cst + 1;
      pq.push(mpr(cst + 1, mpr(vk, vd)));
    }

    // move free spaces
    for (int i = 0; i < 4; ++i) {
      if (i == ud)  continue;
      vk = uk, vd = i;
      s1 = s2 = g1 = g2 = uk;
      s1.frs += kNxt2[ud][0][0], s1.scn += kNxt2[ud][0][1];
      s2.frs += kNxt2[ud][1][0], s2.scn += kNxt2[ud][1][1];
      g1.frs += kNxt2[vd][0][0], g1.scn += kNxt2[vd][0][1];
      g2.frs += kNxt2[vd][1][0], g2.scn += kNxt2[vd][1][1];
      ln = sugar_cube(s1, s2, g1, g2, uk);
      if (f[vk.frs][vk.scn][vd] > cst + ln) {
        f[vk.frs][vk.scn][vd] = cst + ln;
        pq.push(mpr(cst + ln, mpr(vk, vd)));
      }
    }
  }

  cout << (res < kInf ? res : -1) << "\n";
}

int sugar_cube(Pr s1, Pr s2, Pr g1, Pr g2, Pr kp) {
  int ret = kInf;

  // mark king as wall
  for (int i = 0; i <= 1; ++i)
    for (int j = 0; j <= 1; ++j)
      plt[kp.frs + i][kp.scn + j] = '*';

  ret = min(ret, bfs(s1, g1) + bfs(s2, g2));
  ret = min(ret, bfs(s1, g2) + bfs(s2, g1));

  // mark king back as pawn
  for (int i = 0; i <= 1; ++i)
    for (int j = 0; j <= 1; ++j)
      plt[kp.frs + i][kp.scn + j] = 'o';

  return ret;
}

void yee_haw() {
  for (int i = 0; i < 4; ++i) {
    Pr g1, g2;
    g1.frs = king.frs + kNxt2[i][0][0], g1.scn = king.scn + kNxt2[i][0][1];
    g2.frs = king.frs + kNxt2[i][1][0], g2.scn = king.scn + kNxt2[i][1][1];
    f[king.frs][king.scn][i] = min(f[king.frs][king.scn][i],
                                   sugar_cube(fc1, fc2, g1, g2, king));
  }
}

int bfs(Pr ss, Pr gs) {
  static int vst[52][52], vst_cnt;
  deque< pair< Pr, int > > que;
  Pr cs, ns;
  int stp;

  if (ss == gs)
    return 0;

  vst[ss.frs][ss.scn] = ++vst_cnt, que.pbk(mpr(ss, 0));
  while (!que.empty()) {
    cs = que.front().frs, stp = que.front().scn, que.pop_front();
    for (int i = 0; i < 4; ++i) {
      ns = cs, ns.frs += kNxt1[i][0], ns.scn += kNxt1[i][1];
      if (plt[ns.frs][ns.scn] == 'o' && vst[ns.frs][ns.scn] != vst_cnt) {
        if (ns == gs)
          return stp + 1;
        vst[ns.frs][ns.scn] = vst_cnt, que.pbk(mpr(ns, stp + 1));
      }
    }
  }

  return kInf;
}

Measured memory_bytes: 1276