#include <bits/stdc++.h>
using namespace std;
char wall = '#';
tuple<long long, long long, long long> dfs(vector<vector<char>> maze,
                                           pair<long long, long long> start) {
  tuple<long long, long long, long long> res;
  queue<tuple<long long, long long, long long>> q;
  long long M = -1;
  vector<vector<long long>> already_went(
      maze.size(), vector<long long>(maze.at(0).size(), 0));
  tuple<long long, long long, long long> temp;
  get<0>(temp) = start.first;
  get<1>(temp) = start.second;
  get<2>(temp) = 0;
  q.push(temp);
  while (!q.empty()) {
    tuple<long long, long long, long long> check = q.front();
    q.pop();
    if (already_went.at(get<0>(check)).at(get<1>(check)) == 1) {
      continue;
    }
    already_went.at(get<0>(check)).at(get<1>(check)) = 1;
    if (get<2>(check) > M) {
      M = get<2>(check);
      res = make_tuple(get<0>(check), get<1>(check), M);
    }
    if (maze.at(get<0>(check) + 1).at(get<1>(check)) != wall) {
      get<0>(temp) = get<0>(check) + 1;
      get<1>(temp) = get<1>(check);
      get<2>(temp) = get<2>(check) + 1;
      q.push(temp);
    }
    if (maze.at(get<0>(check)).at(get<1>(check) + 1) != wall) {
      get<0>(temp) = get<0>(check);
      get<1>(temp) = get<1>(check) + 1;
      get<2>(temp) = get<2>(check) + 1;
      q.push(temp);
    }
    if (maze.at(get<0>(check) - 1).at(get<1>(check)) != wall) {
      get<0>(temp) = get<0>(check) - 1;
      get<1>(temp) = get<1>(check);
      get<2>(temp) = get<2>(check) + 1;
      q.push(temp);
    }
    if (maze.at(get<0>(check)).at(get<1>(check) - 1) != wall) {
      get<0>(temp) = get<0>(check);
      get<1>(temp) = get<1>(check) - 1;
      get<2>(temp) = get<2>(check) + 1;
      q.push(temp);
    }
  }
  return res;
}
int main() {
  long long H, W;
  cin >> H >> W;
  vector<vector<char>> maze(H + 2, vector<char>(W + 2, '#'));
  pair<long long, long long> start;
  for (long long i = 1; i < H + 1; ++i) {
    for (long long j = 1; j < W + 1; ++j) {
      cin >> maze.at(i).at(j);
      if (maze.at(i).at(j) == '.') {
        start = {i, j};
      }
    }
  }
  vector<pair<long long, long long>> before = {start, {-1, -1}};
  while (true) {
    tuple<long long, long long, long long> next = dfs(maze, before.at(0));
    if (get<0>(next) == before.at(1).first &&
        get<1>(next) == before.at(1).second) {
      cout << get<2>(next) << endl;
      break;
    }
    before.at(1) = before.at(0);
    before.at(0) = {get<0>(next), get<1>(next)};
  }
}
