#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> P;

#define EACH(i,a) for (auto& i : a)
#define FOR(i,a,b) for (ll i=(a);i<(b);i++)
#define RFOR(i,a,b) for (ll i=(b)-1;i>=(a);i--)
#define REP(i,n) for (ll i=0;i<(n);i++)
#define RREP(i,n) for (ll i=(n)-1;i>=0;i--)
#define debug(x) cout<<#x<<": "<<x<<endl
#define pb push_back
#define ALL(a) (a).begin(),(a).end()

const ll linf = 1e18;
const int inf = 1e9;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
	EACH(x,vec) is >> x;
	return is;
}
/*
template<class... T>
ostream& operator<<(ostream& os, tuple<T...>& t) {
	for (size_t i = 0; i < tuple_size< tuple<T...> >::value; ++i) {
		if (i) os << " ";
		os << get<0>(t);
	}
	return os;
}
*/
template<typename T>
ostream& operator<<(ostream& os, vector<T>& vec) {
	REP(i,vec.size()) {
		if (i) os << " ";
		os << vec[i];
	}
	return os;
}
template<typename T>
ostream& operator<<(ostream& os, vector< vector<T> >& vec) {
	REP(i,vec.size()) {
		if (i) os << endl;
		os << vec[i];
	}
	return os;
}

const int W = 15, H = 19;
const int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
const int dy[] = {-1, -1, 0, 1, 1, 1, 0, -1};

bool inRange(int x, int y) {
	return 0 <= x && x < W && 0 <= y && y < H;
}
bool isGoal(int x, int y) {
	return y >= H || (y == H-1 && inRange(x, y));
}

struct Node {
	int x, y, f;
};

vector<P> v;
map<int, map<int, map<int, int> > > dist;
int sid[H][W];

Node Go(const Node& node, int dir) {
	Node res = node;
	int x = node.x, y = node.y, f = node.f;
//	cout << "Go:" << x << " " << y << " " << dir << " " << f << endl;
	int nx = x+dx[dir], ny = y+dy[dir];
	if ( isGoal(x, y) ) return res;
	if ( !inRange(x, y) ) return {0, 0, -1};
	if ( sid[y][x] < 0 || (f & (1 << sid[y][x])) ) return res;
	res.x = nx, res.y = ny;
	res.f = f | (1 << sid[y][x]);
	return Go(res, dir);
}
Node GoFirst(const Node& node, int dir) {
	Node res = {0, 0, -1};
	int x = node.x, y = node.y, f = node.f;
	int nx = x+dx[dir], ny = y+dy[dir];
	if ( !inRange(nx, ny) ) return res;
	if ( sid[ny][nx] < 0 || (f & (1 << sid[ny][nx])) ) return res;
	res.x = nx;
	res.y = ny;
	res.f = f;
	return Go(res, dir);
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	vector<string> m(H); cin >> m;
	int sx = -1, sy = -1;
	REP(y, H) REP(x, W) {
		if (m[y][x] == 'O') {
			sx = x, sy = y;
		}
		if (m[y][x] == 'X') {
			v.pb( P(x, y) );
		}
	}
	assert(sx >= 0);

	int N = v.size();
	fill(sid[0], sid[H], -1);
	REP(i, N) {
		int x = v[i].first, y = v[i].second;
		sid[y][x] = i;
	}

	ll ans = 0;
	queue<Node> Q; Q.push({sx, sy, 0});
//	fill(dist[0][0], dist[H-1][W], inf);
	dist[sy][sx][0] = 1;
	if (isGoal(sx, sy)) ans = 1;
	while ( !Q.empty() ) {
		Node node = Q.front(); Q.pop();
		int x = node.x, y = node.y, f = node.f;
//		cout << x << " " << y << " " << f << endl;
		REP(i, 8) {
			Node n = GoFirst(node, i);
			if (n.f >= 0) {
				if ( isGoal(n.x, n.y) ) {
					if (ans == 0 || dist[y][x][f]+1 < ans) {
						ans = dist[y][x][f]+1;
//					cout << "goal" << endl;
					}
				}
				else if (dist[n.y][n.x][n.f] == 0 || dist[y][x][f]+1 < dist[n.y][n.x][n.f]) {
					dist[n.y][n.x][n.f] = dist[y][x][f]+1;
					Q.push(n);
				}
			}
		}
	}
	if (ans == 0) cout << -1 << endl;
	else cout << ans-1 << endl;
}

Measured memory_bytes: 7160