// Slower C++ solution:
#include <bits/stdc++.h>



using namespace std;

int n, m;

char op[1005][1005];

bool vis[1005][1005];

int dp[1005][1005];

const int X[] = {-1, 0, 1, 0}, Y[] = {0, 1, 0, -1};



struct Node {

    int x, y;



    Node(int a, int b) : x(a), y(b) {}

};



queue<Node> que;



int main() {

    ios::sync_with_stdio(false), memset(dp, 127, sizeof(dp));

    cin >> n >> m;

    for (int i = 1; i <= n; i++)cin >> (op[i] + 1);

    for (int i = 1; i <= n; i++) {

        for (int j = 1; j <= m; j++) {

            if (op[i][j] == '#') {

                for (int p = 0; p < 4; p++) {

                    int xx = i + X[p], yy = j + Y[p];

                    if (op[xx][yy] == '.' && !vis[xx][yy])vis[xx][yy] = true, dp[xx][yy] = 1, que.push(Node(xx, yy));

                }

            }

        }

    }

    while (!que.empty()) {

        Node s = que.front();

        que.pop(), vis[s.x][s.y] = false;

        for (int i = 0; i < 4; i++) {

            int xx = s.x + X[i], yy = s.y + Y[i];

            if (xx < 1 || xx > n || yy < 1 || yy > m)continue;

            if (op[xx][yy] == '.' && dp[xx][yy] > dp[s.x][s.y] + 1) {

                dp[xx][yy] = dp[s.x][s.y] + 1;

                if (!vis[xx][yy])que.push(Node(xx, yy)), vis[xx][yy] = true;

            }

        }

    }

    int ans = 0;

    for (int i = 1; i <= n; i++) {

        for (int j = 1; j <= m; j++) {

            if (op[i][j] == '.')ans = max(ans, dp[i][j]);

        }

    }

    cout << ans;

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 5.14647689449055x):
#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

int main(void){

    // Your code here!

int H,W;

cin >> H>>W;

vector<vector<char>> v(H);

vector<pair<int,int>> K;

for ( int i = 0 ; i < H ; i++ )

   v[i].resize(W);

   

   for(int i=0;i< H;i++)

      for(int j=0;j<W;j++){

                  char x;

                  cin >> x;

                  v[i][j]=x;

                  if(x=='#')

                    K.push_back(make_pair(i,j));

      }

      int count=0;

     int prevn=0;

     

      while(1){

          int n=K.size();

          int c=0;

            int OK=0;

          for(int l=prevn;l<n;l++){

              int i=K[l].first;

              int j=K[l].second;

            

              if(i>0)

                 if(v[i-1][j]=='.'){

                     v[i-1][j]='#';

                     K.push_back(make_pair(i-1,j));

                     c++;

                  //   cout << "Jos";

                 }

                     

            if(i<(H-1)) 

                 if(v[i+1][j]=='.'){

                    v[i+1][j]='#';

                    K.push_back(make_pair(i+1,j));

                    c++;

                  //  cout << "Sus";

                 }

               if(j>0)

                 if(v[i][j-1]=='.'){

                     v[i][j-1]='#';

                     K.push_back(make_pair(i,j-1));

                     c++;

                   //  cout << "Stanga";

                 }

                     

            if(j<(W-1)) 

                 if(v[i][j+1]=='.'){

                     v[i][j+1]='#';

                     K.push_back(make_pair(i,j+1));

                     c++;

                  //   cout <<  "Dreapta";

                     

                 }

               //  cout << endl;

                 if(c!=0)

                   OK=1;

                /*   cout << c << endl << endl;

                   for(int f=0;f<H;f++){

                        for(int g=0;g<W;g++)

                           cout << v[f][g];

                           cout << endl;

                   }

                   cout << endl << endl;*/

                 

          }

         // cout << "asddddddddd" << endl << endl << endl << endl << endl << endl;

          if(!OK)

             break;

          count++;

          prevn=n;

          

          

      }

      cout << count;

   

               

}