#include <bits/stdc++.h>
constexpr int kMod = 1000000007;
constexpr char kcWall = '#';
constexpr char kcPath = '.';
int main() {
  int H, W;
  std::cin >> H >> W;
  bool available[21][21];
  int s[21][21];
  for (int h = 0; h < H; ++h) {
    for (int w = 0; w < W; ++w) {
      char c;
      std::cin >> c;
      if (c == kcWall)
        available[h][w] = false;
      else
        available[h][w] = true;
      s[h][w] = -1;
    }
  }
  std::deque<std::pair<int, int>> que;
  que.push_back({0, 0});
  int max_h = 0, max_w = 0, max_c = 0;
  while (!que.empty()) {
    auto pair = que.front();
    que.pop_front();
    int h = pair.first;
    int w = pair.second;
    if (s[h][w] >= 0) continue;
    int cost = INT_MAX;
    int nh, nw;
    nh = h - 1;
    nw = w;
    if (nh >= 0 && available[nh][nw]) {
      if (s[nh][nw] >= 0)
        cost = std::min(cost, s[nh][nw] + 1);
      else
        que.push_back({nh, nw});
    }
    nh = h + 1;
    nw = w;
    if (nh < H && available[nh][nw]) {
      if (s[nh][nw] >= 0)
        cost = std::min(cost, s[nh][nw] + 1);
      else
        que.push_back({nh, nw});
    }
    nh = h;
    nw = w - 1;
    if (nw >= 0 && available[nh][nw]) {
      if (s[nh][nw] >= 0)
        cost = std::min(cost, s[nh][nw] + 1);
      else
        que.push_back({nh, nw});
    }
    nh = h;
    nw = w + 1;
    if (nw < W && available[nh][nw]) {
      if (s[nh][nw] >= 0)
        cost = std::min(cost, s[nh][nw] + 1);
      else
        que.push_back({nh, nw});
    }
    s[h][w] = (cost < INT_MAX) ? cost : 0;
    if (s[h][w] > max_c) {
      max_h = h;
      max_w = w;
      max_c = s[h][w];
    }
  }
  for (int h = 0; h < H; ++h) {
    for (int w = 0; w < W; ++w) {
      s[h][w] = -1;
    }
  }
  que.push_back({max_h, max_w});
  max_c = 0;
  while (!que.empty()) {
    auto pair = que.front();
    que.pop_front();
    int h = pair.first;
    int w = pair.second;
    if (s[h][w] >= 0) continue;
    int cost = INT_MAX;
    int nh, nw;
    nh = h - 1;
    nw = w;
    if (nh >= 0 && available[nh][nw]) {
      if (s[nh][nw] >= 0)
        cost = std::min(cost, s[nh][nw] + 1);
      else
        que.push_back({nh, nw});
    }
    nh = h + 1;
    nw = w;
    if (nh < H && available[nh][nw]) {
      if (s[nh][nw] >= 0)
        cost = std::min(cost, s[nh][nw] + 1);
      else
        que.push_back({nh, nw});
    }
    nh = h;
    nw = w - 1;
    if (nw >= 0 && available[nh][nw]) {
      if (s[nh][nw] >= 0)
        cost = std::min(cost, s[nh][nw] + 1);
      else
        que.push_back({nh, nw});
    }
    nh = h;
    nw = w + 1;
    if (nw < W && available[nh][nw]) {
      if (s[nh][nw] >= 0)
        cost = std::min(cost, s[nh][nw] + 1);
      else
        que.push_back({nh, nw});
    }
    s[h][w] = (cost < INT_MAX) ? cost : 0;
    if (s[h][w] > max_c) {
      max_c = s[h][w];
    }
  }
  std::cout << max_c << std::endl;
}
