//BFS写的有问题,能过前三个案例,后三个超时
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int N = 110;
char g[N][N];
bool st[N][N];
int destr, destc;
string routes[N][N];
int n,m;
bool question[N][N];
bool next_question[N][N];
int dy[4] = {0,1,0,-1}, dx[4] = {-1,0,1,0};
struct Point{
int row,col;
string path;
bool operator<(const Point& t) const{
return path.size() > t.path.size();
}
};
void bfs(int row,int col){
memset(st,false,sizeof st);
priority_queue<Point> heap;
heap.push({row,col,""});
st[row][col] = true;
while(!heap.empty()){
int size = heap.size();
string ans = "";
for(int k = 0; k < size; k++){
auto p = heap.top(); heap.pop();
for(int i = 0; i < 4; i++){
int nx = p.row + dx[i];
int ny = p.col + dy[i];
if(nx == destr && ny == destc) {
routes[row][col] = p.path + to_string(i);
return;
}
if(nx >= 0 && nx < n && ny >= 0 && ny < m && !st[nx][ny] && (g[nx][ny] == 'O' || g[nx][ny] == 'X')) {
if(routes[nx][ny].size() != 0 && routes[nx][ny].size() < ans.size()){
ans = p.path + to_string(i) + routes[nx][ny];
}
string nextp = p.path + to_string(i);
heap.push({nx,ny,nextp});
st[nx][ny] = true;
}
}
}
if(ans.size()){
routes[row][col] = ans;
return;
}
}
}
void go(int& row,int& col,string path){
for(int i = 0; i < path.size(); i++){
if(path[i] == '0' && row - 1 >= 0 && (g[row-1][col] == 'O' || g[row-1][col] == 'X')) row--;
else if(path[i] == '1' && col + 1 < m && (g[row][col + 1] == 'O'|| g[row][col + 1] == 'X')) col++;
else if(path[i] == '2' && row + 1 < n && (g[row+1][col] == 'O' || g[row+1][col] == 'X') ) row++;
else if(path[i] == '3' && col - 1 >= 0 && (g[row][col - 1] == 'O' || g[row][col - 1] == 'X') ) col--;
if(g[row][col] == 'X') return;
}
}
int main(){
scanf("%d%d",&n,&m);
getchar();
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
scanf("%c",&g[i][j]);
}
getchar();
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
char c = g[i][j];
if(c == 'X') {
destr = i;
destc = j;
break;
}
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
char c = g[i][j];
if(c == 'O'){
bfs(i,j);
question[i][j] = true;
}
}
}
string ans;
while(true){
int nr = -1,nc = -1;
for(int i = n - 1; i >= 0; i--){
for(int j = 0; j < m; j++){
if(!question[i][j]) continue;
if(nr == -1 || routes[i][j].size() > routes[nr][nc].size()){
nr = i;
nc = j;
}
}
}
if(nr == -1) break;
string ss = routes[nr][nc];
ans += routes[nr][nc];
memset(next_question,false,sizeof next_question);
for(int i = n - 1; i >= 0; i--){
for(int j = 0; j < m; j++){
if(!question[i][j]) continue;
int nr = i,nc = j;
go(nr,nc,ss);
if(g[nr][nc] != 'X'){
next_question[nr][nc] = true;
}
}
}
for(int i = n - 1; i >= 0; i--){
for(int j = 0; j < m; j++){
question[i][j] = next_question[i][j];
}
}
}
cout << ans << endl;
}