#include <bits/stdc++.h>
const int INF = 1001001001;
const int diri[] = {1, 0, -1, 0};
const int dirj[] = {0, 1, 0, -1};
int main() {
  int h, w;
  std::cin >> h >> w;
  std::cout << h << w << std::endl;
  std::vector<std::string> s(h);
  int answer = 0;
  for (int i = 0; i < h; i++) {
    std::cin >> s[i];
  }
  for (int si = 0; si < h; si++) {
    for (int sj = 0; sj < w; sj++) {
      if (s[si][sj] == '#') {
        continue;
      }
      std::vector<std::vector<int>> dist(h, std::vector<int>(w, INF));
      std::queue<std::pair<int, int>> q;
      auto update = [&](int i, int j, int value) {
        if (dist[i][j] != INF) {
          return;
        }
        dist[i][j] = value;
        q.push(std::pair<int, int>(i, j));
      };
      update(si, sj, 0);
      while (!q.empty()) {
        int i = q.front().first;
        int j = q.front().second;
        q.pop();
        for (int dir = 0; dir < 4; dir++) {
          int ni = i + diri[dir];
          int nj = j + dirj[dir];
          if (ni < 0 || nj < 0 || ni >= h || nj >= w) {
            continue;
          }
          if (s[ni][nj] == '#') {
            continue;
          }
          update(ni, nj, dist[i][j] + 1);
        }
      }
      for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
          if (dist[i][j] == INF) {
            continue;
          }
          answer = std::max(answer, dist[i][j]);
        }
      }
    }
  }
  return 0;
}
