#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <functional>
#include <string>
#include <queue>
#include <cmath>
#include <iomanip>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <random>
#include <unordered_map>
#include <unordered_set>
#define ll long long
#define fr(i,k,N) for(ll i=k; i<N;i++)
#define rep(i,N) for(ll i=0; i<N;i++)
#define alll(v) v.begin(),v.end()
using namespace std;
template <class X> void pr(X test){cout<<test<<endl;}
template <class X> void prr(X test){for(auto it:test){cout<<it<<endl;}cout<<endl;}

int main() {
    ll a,b;

    cin>>a>>b;
    vector<string> v(a);
    ll mat[a][b];
    rep(i, a) {
        rep(j ,b) mat[i][j] = LLONG_MAX;
    }
    // ..#..#
    // ......
    // #..#..
    // ......
    // .#....
    // ....#.
    rep(i, a){
        cin>>v[i];
    }
    rep(i, a) {
        rep(j ,b){
            if(v[i][j] == '#') {
                mat[i][j]=0;
                continue;
            }
            if(j -1 > 0 && mat[i][j-1] != LLONG_MAX) mat[i][j] = min(mat[i][j], mat[i][j-1] + 1);
            if(i -1 > 0 && mat[i-1][j] != LLONG_MAX) mat[i][j] = min(mat[i][j], mat[i-1][j] + 1);
        }
        rep(j , b){
            ll jx = b - j -1;
            if(v[i][jx] == '#') {
                mat[i][jx]=0;
                continue;
            }
            if(jx+1 < b && mat[i][jx+1] != LLONG_MAX) mat[i][jx] = min(mat[i][jx], mat[i][jx+1] + 1);
            if(i -1 > 0 && mat[i-1][jx] != LLONG_MAX) mat[i][jx] = min(mat[i][jx], mat[i-1][jx] + 1);
        }
    }
    // pr(mat[0][0]);
    rep(ii, a) {
        auto i = a - ii - 1 ;
        rep(j ,b){
            if(v[i][j] == '#') {
                mat[i][j]=0;
                continue;
            }
            if(j -1 > 0 && mat[i][j-1] != LLONG_MAX) mat[i][j] = min(mat[i][j], mat[i][j-1] + 1);
            if(i +1 < a && mat[i+1][j] != LLONG_MAX) mat[i][j] = min(mat[i][j], mat[i+1][j] + 1);
        }
        rep(j , b){
            ll jx = b - j -1;
            if(v[i][jx] == '#') {
                mat[i][jx]=0;
                continue;
            }
            if(jx+1 < b && mat[i][jx+1] != LLONG_MAX) mat[i][jx] = min(mat[i][jx], mat[i][jx+1] + 1);
            if(i +1 > a && mat[i+1][jx] != LLONG_MAX) mat[i][jx] = min(mat[i][jx], mat[i+1][jx] + 1);
        }
    }
    ll mm = 0;
    rep(i, a) {
        rep(j ,b){
            mm = max(mm, mat[i][j]);
        // pr(mm);
        }
    }
    pr(mm);
    return 0;
}

class UF { // union find from https://github.com/kartikkukreja/blog-codes (MIT)
    // [usage]
    // auto uf = new UF(n);
    // uf->merge(a, b);
    // ...
public:
    int *id; // inner id
    int cnt; // number of all vartices
    int *sz; // sz[i] means size of i's set
    UF(int N)   {
        cnt = N;
        id = new int[N];
        sz = new int[N];
        for(int i=0; i<N; i++) {
            id[i] = i;
            sz[i] = 1;
        }
    }
    ~UF() {
        delete [] id;
        delete [] sz;
    }
    int find(int p) {
        int root = p;
        while (root != id[root]) root = id[root];
        while (p != root) {
            int newp = id[p];
            id[p] = root;
            p = newp;
        }
        return root;
    }
    void merge(int x, int y) {
        int i = find(x);
        int j = find(y);
        if (i == j) return;
        
        if (sz[i] < sz[j]) {
            id[i] = j;
            sz[j] += sz[i];
        } else {
            id[j] = i;
            sz[i] += sz[j];
        }
        cnt--;
    }
    bool connected(int x, int y) {
        return find(x) == find(y);
    }
    int count() {
        return cnt;
    }
};

Measured memory_bytes: 9848