#include <bits/stdc++.h>

using namespace std;

namespace {

    typedef double real;
    typedef long long ll;

    int H, W;
    vector<string> F;
    bool input() {
        cin >> H >> W;
        if (H == 0 && W == 0) return false;
        F.clear(); F.resize(H);
        for (int i = 0; i < H; i++) cin >> F[i];
        return true;
    }

    const int INF = 1<<28;
    const int MAX_H = 51;
    const int MAX_W = 51;

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

    struct S {
        int y, x;
        int cost;
        S(int y, int x, int cost) : y(y), x(x), cost(cost) {}
    };
    int dist(int ky, int kx, int sy, int sx, int gy, int gx) {
        vector< vector<bool> > used(H, vector<bool>(W, false));
        queue<S> Q;
        Q.push(S(sy, sx, 0));
        used[sy][sx] = true;
        while (!Q.empty()) {
            S c = Q.front(); Q.pop();
            if (c.y == gy && c.x == gx) return c.cost;
            for (int i = 0; i < 4; i++) {
                int ny = c.y + dy[i];
                int nx = c.x + dx[i];
                if (ny < 0 || ny >= H) continue;
                if (nx < 0 || nx >= W) continue;
                if (F[ny][nx] == '*') continue;
                if (ky <= ny && ny <= ky + 1 && kx <= nx && nx <= kx + 1) continue;
                if (used[ny][nx]) continue;
                used[ny][nx] = true;
                Q.push(S(ny, nx, c.cost + 1));
            }
        }
        return INF;
    }

    struct T {
        int y, x;
        int k; // which direction the king came?
        int cost;
        T(int y, int x, int k, int cost) : y(y), x(x), k(k), cost(cost) {}
    };
    bool operator<(const T& a, const T& b) {
        return a.cost > b.cost;
    }
    ostream& operator<<(ostream& os, const T& t) {
        return os << "T((" << t.y << "," << t.x << "), " << t.k << ", " << t.cost << ")";
    }

    bool check(int y, int x) {
        // can the king move into (y, x)?
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                int ny = y + i;
                int nx = x + j;
                if (ny < 0 || ny >= H) return false;
                if (nx < 0 || nx >= W) return false;
                if (F[ny][nx] == '*') return false;
            }
        }
        return true;
    }

    T move(int k, int y, int x, int past_cost, int sy0, int sx0, int sy1, int sx1) {
        int kny = y + dy[k];
        int knx = x + dx[k];
        if (!check(kny, knx)) throw -1;
        int ny, nx, my, mx;
        switch (k) {
            case 0: ny = y; nx = x - 1; my = y + 1; mx = x - 1; break;
            case 1: ny = y - 1; nx = x; my = y - 1; mx = x + 1; break;
            case 2: ny = y; nx = x + 2; my = y + 1; mx = x + 2; break;
            case 3: ny = y + 2; nx = x; my = y + 2; mx = x + 1; break;
            default: break;
        }
        int cost = min(
                     dist(y, x, ny, nx, sy0, sx0) + dist(y, x, my, mx, sy1, sx1),
                     dist(y, x, ny, nx, sy1, sx1) + dist(y, x, my, mx, sy0, sx0)
                   );
        return T(kny, knx, (k + 2) % 4, past_cost + cost + 1);
    }

    void solve() {
        int sy0, sx0, sy1, sx1;
        int ky, kx;
        int c = 0;
        bool found_king = false;
        for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) {
            if (F[i][j] == 'X' && !found_king) {
                ky = i;
                kx = j;
                found_king = true;
            }
            if (F[i][j] == '.') {
                (c == 0 ? sy0 : sy1) = i;
                (c == 0 ? sx0 : sx1) = j;
                c++;
            }
        }
        assert(c == 2);

        int D[MAX_H][MAX_W][5];
        for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) for (int k = 0; k < 5; k++) D[i][j][k] = INF;
        D[ky][kx][4] = 0;
        priority_queue<T> PQ;
        for (int i = 0; i < 4; i++) {
            try {
                T t = move(i, ky, kx, 0, sy0, sx0, sy1, sx1);
                PQ.push(t);
                D[t.y][t.x][t.k] = t.cost;
            } catch (int e) {}
        }
        while (!PQ.empty()) {
            T c = PQ.top(); PQ.pop();
            for (int i = 0; i < 4; i++) {
                int ny, nx, my, mx;
                switch (c.k) {
                    case 0: ny = c.y; nx = c.x - 1; my = c.y + 1; mx = c.x - 1; break;
                    case 1: ny = c.y - 1; nx = c.x; my = c.y - 1; mx = c.x + 1; break;
                    case 2: ny = c.y; nx = c.x + 2; my = c.y + 1; mx = c.x + 2; break;
                    case 3: ny = c.y + 2; nx = c.x; my = c.y + 2; mx = c.x + 1; break;
                    default: break;
                }
                try {
                    T t = move(i, c.y, c.x, c.cost, ny, nx, my, mx);
                    if (D[t.y][t.x][t.k] > t.cost) {
                        PQ.push(t);
                        D[t.y][t.x][t.k] = t.cost;
                    }
                } catch (int e) {}
            }
        }
        int ans = INF;
        for (int i = 0; i < 5; i++) {
            ans = min(ans, D[0][0][i]);
        }
        if (ans == INF) ans = -1;
        cout << ans << endl;
    }
}

int main() {
    while (input()) solve();
    return 0;
}

Measured memory_bytes: 1348