#include <bits/stdc++.h>
using namespace std;
int main(int argc, char** argv) {
  int h, w;
  cin >> h >> w;
  using coord = pair<int, int>;
  queue<coord> starts;
  char maze[h + 1][w + 1];
  int dp[h + 1][w + 1];
  for (int i = 0; i < w + 1; ++i) {
    maze[0][i] = '#';
    maze[h][i] = '#';
  }
  for (int i = 0; i < h + 1; ++i) {
    maze[i][0] = '#';
    maze[i][w] = '#';
  }
  for (int i = 0; i < h; ++i) {
    string s;
    cin >> s;
    for (int j = 0; j < s.size(); ++j) {
      maze[i + 1][j + 1] = s[j];
    }
  }
  for (int i = 0; i < h + 1; ++i) {
    for (int j = 0; j < w + 1; ++j) {
      if (maze[i][j] != '#') starts.push(coord(j, i));
    }
  }
  int dist = 0;
  while (!starts.empty()) {
    coord cur = starts.front();
    starts.pop();
    for (int i = 0; i < h + 1; ++i) {
      for (int j = 0; j < w + 1; ++j) {
        if (maze[i][j] == '#')
          dp[i][j] = -1;
        else
          dp[i][j] = 0;
      }
    }
    queue<coord> next;
    next.push(cur);
    while (!next.empty()) {
      cur = next.front();
      next.pop();
      int x = cur.first;
      int y = cur.second;
      int minp = h * w;
      switch (dp[y - 1][x]) {
        case 0:
          next.push(coord(x, y - 1));
        case -1:
          break;
        default:
          minp = min(minp, dp[y - 1][x]);
      }
      switch (dp[y + 1][x]) {
        case 0:
          next.push(coord(x, y + 1));
        case -1:
          break;
        default:
          minp = min(minp, dp[y + 1][x]);
      }
      switch (dp[y][x - 1]) {
        case 0:
          next.push(coord(x - 1, y));
        case -1:
          break;
        default:
          minp = min(minp, dp[y][x - 1]);
      }
      switch (dp[y][x + 1]) {
        case 0:
          next.push(coord(x + 1, y));
        case -1:
          break;
        default:
          minp = min(minp, dp[y][x + 1]);
      }
      if (minp < h * w)
        dp[y][x] = minp + 1;
      else
        dp[y][x] = 1;
      dist = max(dist, dp[y][x]);
    }
  }
  cout << dist - 1 << endl;
}
