// Slower C++ solution:
#include <iostream>

#include <cstdio>

#include <queue>

#include <cstring>

using namespace std;



//char s[1003][1003];

int vis[1003][1003];

struct node

{

    int x;int y;

};



int main()

{

    int h,w;

    cin>>h>>w;

    queue<node> q;

    memset(vis,0,sizeof(vis));

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

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

            char s;cin>>s;

            if(s=='#'){

                node a;a.x=i;a.y=j;

                q.push(a);

                vis[i][j]=1;

            }

        }

    }

    while(!q.empty()){

        node a;a=q.front();q.pop();

        if(a.x>0&&!vis[a.x-1][a.y]){

            vis[a.x-1][a.y]=vis[a.x][a.y]+1;

            node b;b.x=a.x-1;b.y=a.y;

            q.push(b);

        }

        if(a.y>0&&!vis[a.x][a.y-1]){

            vis[a.x][a.y-1]=vis[a.x][a.y]+1;

            node b;b.x=a.x;b.y=a.y-1;

            q.push(b);

        }

        if(a.x<h-1&&!vis[a.x+1][a.y]){

            vis[a.x+1][a.y]=vis[a.x][a.y]+1;

            node b;b.x=a.x+1;b.y=a.y;

            q.push(b);

        }

        if(a.y<w-1&&!vis[a.x][a.y+1]){

            vis[a.x][a.y+1]=vis[a.x][a.y]+1;

            node b;b.x=a.x;b.y=a.y+1;

            q.push(b);

        }

    }

    int ans=0;

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

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

            ans=max(ans,vis[i][j]);

            //cout<<vis[i][j];

        }

        //cout<<endl;

    }

    cout<<ans-1<<endl;

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 5.011278666348883x):
#include <bits/stdc++.h>

using namespace std;



int n, m;

char arr[1010][1010];

int ans[1010][1010];

bool visited[1010][1010];

queue<pair<int, int>>bfs;



void solve(){

	while (!bfs.empty()){

		pair<int, int> tmp = bfs.front();

		bfs.pop();

		int temp1, temp2;



		temp1 = tmp.first+1;

		temp2 = tmp.second;

		if (temp1 >= 0 && temp2 >= 0 && temp1 < n && temp2 < m && !visited[temp1][temp2]){

			visited[temp1][temp2] = true;

			ans[temp1][temp2] = ans[tmp.first][tmp.second] + 1;

			bfs.push({temp1, temp2});

		}

		temp1 = tmp.first;

		temp2 = tmp.second+1;

		if (temp1 >= 0 && temp2 >= 0 && temp1 < n && temp2 < m && !visited[temp1][temp2]){

			visited[temp1][temp2] = true;

			ans[temp1][temp2] = ans[tmp.first][tmp.second] + 1;

			bfs.push({temp1, temp2});

		}

		temp1 = tmp.first-1;

		temp2 = tmp.second;

		if (temp1 >= 0 && temp2 >= 0 && temp1 < n && temp2 < m && !visited[temp1][temp2]){

			visited[temp1][temp2] = true;

			ans[temp1][temp2] = ans[tmp.first][tmp.second] + 1;

			bfs.push({temp1, temp2});

		}

		temp1 = tmp.first;

		temp2 = tmp.second-1;

		if (temp1 >= 0 && temp2 >= 0 && temp1 < n && temp2 < m && !visited[temp1][temp2]){

			visited[temp1][temp2] = true;

			ans[temp1][temp2] = ans[tmp.first][tmp.second] + 1;

			bfs.push({temp1, temp2});

		}

	}	

}



int main(){

	ios_base::sync_with_stdio(0); cin.tie(0);



	cin >> n >> m;

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

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

			cin >> arr[i][j];

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

				bfs.push({i, j});

				visited[i][j] = true;

			}

		}

	}



	solve();



	int anss = 0;

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

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

			anss = max(anss, ans[i][j]);

		}

	}



	cout << anss << endl;



	return 0;

}