#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
#define SIZE 51
#define qSIZE 160
char map[SIZE][SIZE];
int visit[SIZE][SIZE][1 << 7];
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };int n, m, stx, sty;
struct point {
int x, y, k;
}queArr[qSIZE * qSIZE];
queue<point> que;
int x, y, k;
int nx, ny, nk;
int front, rear;
int bfs() {
front = rear = -1;
visit[stx][sty][0] = 1;
// que.push({ stx,sty,0 });
rear++;
queArr[rear].x = stx;
queArr[rear].y = sty;
queArr[rear].k = 0;
// while(!que.empty()){
while (rear != front) {
// x = que.front().x;
// y = que.front().y;
// k = que.front().k;
// que.pop();
front++;
x = queArr[front].x;
y = queArr[front].y;
k = queArr[front].k;
if (map[x][y] == '1') return visit[x][y][k] - 1;
for (int i = 0; i < 4; i++) {
nx = x + dx[i];
ny = y + dy[i];
if (nx < 0 || ny < 0 || nx >= n || ny >= m || map[nx][ny] == '#' || visit[nx][ny][k] != 0) continue;
if ('a' <= map[nx][ny] && map[nx][ny] <= 'f') {
nk = k | (1 << (map[nx][ny] - 'a'));
if (visit[nx][ny][nk] == 0) {
visit[nx][ny][nk] = visit[x][y][k] + 1;
// que.push({ nx,ny,nk });
rear++;
queArr[rear].x = nx;
queArr[rear].y = ny;
queArr[rear].k = nk;
}
}
else if ('A' <= map[nx][ny] && map[nx][ny] <= 'F') {
nk = k&(1 << map[nx][ny] - 'A');
if (nk != 0) {
visit[nx][ny][k] = visit[x][y][k] + 1;
//que.push({ nx,ny,k });
rear++;
queArr[rear].x = nx;
queArr[rear].y = ny;
queArr[rear].k = k;
}
}
else if (visit[nx][ny][k] == 0) {
visit[nx][ny][k] = visit[x][y][k] + 1;
//que.push({ nx,ny,k });
rear++;
queArr[rear].x = nx;
queArr[rear].y = ny;
queArr[rear].k = k;
}
}
}
return -1;
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> map[i];
for (int j = 0; j < m; j++) {
if (map[i][j] == '0') {
stx = i;
sty = j;
}
}
}
cout << bfs() << endl;
}