#include <bits/stdc++.h>
using namespace std;
template <typename T>
void arrout(T arr[], int len) {
  for (int i = 0; i <= len; ++i) cout << arr[i] << " ";
  cout << endl;
}
int OK = 1;
const int INF = 0x3f3f3f3f;
const int maxn = 1010;
char gra[maxn][maxn];
int dist[4][maxn][maxn];
int dist2[4][4];
int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int n, m;
struct node {
  int x, y;
  node(int xx = 0, int yy = 0) {
    x = xx;
    y = yy;
  }
};
bool check(int x, int y) {
  if (x < 1 || x > n || y < 1 || y > m) return false;
  if (gra[x][y] != '.') return false;
  return true;
}
void getdist(char tp) {
  queue<node> que;
  int ind = tp - '0';
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
      if (gra[i][j] != tp) continue;
      if (gra[i + 1][j] == tp && gra[i - 1][j] == tp && gra[i][j + 1] == tp &&
          gra[i][j - 1] == tp)
        continue;
      que.push(node(i, j));
      dist[ind][i][j] = 0;
    }
  }
  int x, y, xx, yy;
  while (!que.empty()) {
    x = que.front().x;
    y = que.front().y;
    ;
    ;
    que.pop();
    for (int i = 0; i < 4; ++i) {
      xx = x + dir[i][0];
      yy = y + dir[i][1];
      ;
      ;
      if ('1' <= gra[xx][yy] && gra[xx][yy] <= '3' && gra[xx][yy] != tp &&
          dist2[ind][gra[xx][yy] - '0'] == -1) {
        dist2[ind][gra[xx][yy] - '0'] = dist[ind][x][y];
        ;
        ;
        ;
        ;
      }
      if (dist[ind][xx][yy] != -1) continue;
      if (!check(xx, yy)) continue;
      dist[ind][xx][yy] = dist[ind][x][y] + 1;
      que.push(node(xx, yy));
    }
  }
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; ++i) scanf("%s", gra[i] + 1);
  memset((dist), -1, sizeof(dist));
  memset((dist2), -1, sizeof(dist2));
  dist2[1][1] = dist2[2][2] = dist2[3][3] = 0;
  getdist('1');
  getdist('2');
  getdist('3');
  int ans = INF;
  int t = 0;
  bool flag = false;
  for (int i = 1; i <= 3; ++i) {
    t = 0;
    flag = false;
    for (int j = 1; j <= 3; ++j) {
      if (dist2[i][j] == -1) {
        flag = true;
        break;
      }
      t += dist2[i][j];
    }
    if (!flag) ans = min(ans, t);
  }
  for (int k = 1; k <= 3; ++k)
    ;
  ;
  for (int k = 1; k <= 3; ++k)
    for (int i = 1; i <= n; ++i)
      ;
  ;
  ;
  ;
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
      if (gra[i][j] != '.') continue;
      if (dist[1][i][j] == -1 || dist[2][i][j] == -1 || dist[3][i][j] == -1)
        continue;
      ans = min(ans, dist[1][i][j] + dist[3][i][j] + dist[2][i][j] - 2);
      if (ans < 0) {
        ;
        ;
      }
    }
  }
  if (ans == INF)
    puts("-1");
  else
    cout << ans << endl;
  return 0;
}
