#include <bits/stdc++.h>
using namespace std;
const long long MX = 1e6 + 9, INF = 1e9;
vector<long long> adj[MX], roots[4];
long long mrk[MX], dis[4][MX];
void BFS(long long col) {
  fill(mrk, mrk + MX, 0);
  fill(dis[col], dis[col] + MX, INF);
  queue<long long> q;
  for (long long i = 0; i < roots[col].size(); i++)
    q.push(roots[col][i]), mrk[roots[col][i]] = 1, dis[col][roots[col][i]] = 0;
  while (!q.empty()) {
    long long u = q.front();
    q.pop();
    for (auto v : adj[u])
      if (!mrk[v]) {
        mrk[v] = 1;
        dis[col][v] = dis[col][u] + 1;
        q.push(v);
      }
  }
}
int32_t main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  long long n, m;
  cin >> n >> m;
  string s[n];
  for (long long i = 0; i < n; i++) cin >> s[i];
  for (long long i = 0; i < n; i++) {
    for (long long j = 0; j < m; j++) {
      long long u = i * m + j;
      if (s[i][j] != '#') {
        if (i > 0 && s[i - 1][j] != '#') adj[u].push_back(u - m);
        if (i < n - 1 && s[i + 1][j] != '#') adj[u].push_back(u + m);
        if (j > 0 && s[i][j - 1] != '#') adj[u].push_back(u - 1);
        if (j < m - 1 && s[i][j + 1] != '#') adj[u].push_back(u + 1);
      }
      if (s[i][j] == '1') roots[1].push_back(u);
      if (s[i][j] == '2') roots[2].push_back(u);
      if (s[i][j] == '3') roots[3].push_back(u);
    }
  }
  BFS(1);
  BFS(2);
  BFS(3);
  long long ans = INF;
  for (long long i = 0; i < n * m; i++)
    ans = min(ans, dis[1][i] + dis[2][i] + dis[3][i] - 2);
  for (long long k = 1; k < 4; k++) {
    long long min1 = INF, min2 = INF, min3 = INF;
    for (long long i = 0; i < roots[k].size(); i++) {
      min1 = min(min1, dis[1][roots[k][i]]);
      min2 = min(min2, dis[2][roots[k][i]]);
      min3 = min(min3, dis[3][roots[k][i]]);
    }
    ans = min(ans, min1 + min2 + min3 - 2);
  }
  if (ans > INF - 10) return cout << -1, 0;
  cout << ans;
  return 0;
}
