#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e3 + 5;
int dis[4][MAX][MAX];
int n, m;
char grid[MAX][MAX];
pair<int, int> start[4];
vector<pair<int, int> > dir{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
inline bool inside(int x, int y) { return x >= 0 && x < n && y >= 0 && y < m; }
void bfs(pair<int, int> source, int d[MAX][MAX]) {
  memset(d, -1, sizeof dis[0]);
  deque<pair<int, int> > dq;
  dq.emplace_front(source.first, source.second);
  d[source.first][source.second] = 0;
  while (!dq.empty()) {
    pair<int, int> cur = dq.front();
    dq.pop_front();
    int x, y;
    tie(x, y) = cur;
    for (auto &each : dir) {
      int nx = x + each.first;
      int ny = y + each.second;
      if (inside(nx, ny)) {
        if (d[nx][ny] == -1) {
          if (grid[nx][ny] >= '1' && grid[nx][ny] <= '3') {
            d[nx][ny] = d[x][y];
            dq.emplace_front(nx, ny);
          } else if (grid[nx][ny] == '.') {
            d[nx][ny] = d[x][y] + 1;
            dq.emplace_back(nx, ny);
          }
        }
      }
    }
  }
}
int main() {
  scanf("%d %d%*c", &n, &m);
  for (int i = int(0); i < int(n); i++) {
    for (int j = int(0); j < int(m); j++) {
      scanf("%c", &grid[i][j]);
      if (grid[i][j] >= '1' && grid[i][j] <= '3') {
        start[grid[i][j] - '0'] = make_pair(i, j);
      }
    }
    scanf("%*c");
  }
  for (int i = int(1); i < int(4); i++) {
    bfs(start[i], dis[i]);
  }
  int ans = 1 << 30;
  for (int i = int(0); i < int(n); i++) {
    for (int j = int(0); j < int(m); j++) {
      if (dis[1][i][j] != -1 && dis[2][i][j] != -1 && dis[3][i][j] != -1) {
        int cur = dis[1][i][j] + dis[2][i][j] + dis[3][i][j];
        if (grid[i][j] == '.') {
          cur -= 2;
        }
        ans = min(ans, cur);
      }
    }
  }
  if (ans != (1 << 30)) {
    printf("%d\n", ans);
  } else {
    puts("-1");
  }
  return 0;
}
