// Original C++ solution (slower):
#include "bits/stdc++.h"



// Begin {{{

using namespace std;



#define all(x) x.begin(), x.end()

#define rep(i, n) for (i64 i = 0; i < (n); ++i)

#define reps(i, s, n) for (i64 i = (s); i <= (n); ++i)

#define VAR(Type, ...) Type __VA_ARGS__; IN(__VA_ARGS__)



using i64 = int_fast64_t;

using pii = pair<i64, i64>;



template <class A, class B>

inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }



template <class A, class B>

inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }



constexpr int INF = 0x3f3f3f3f;

constexpr i64 LINF = 0x3f3f3f3f3f3f3f3fLL;

constexpr int MOD = int(1e9) + 7;



// IN

void IN() {}

template <class Head, class... Tail>

void IN(Head&& head, Tail&&... tail) {

  cin >> head;

  IN(forward<Tail>(tail)...);

}



// OUTS

void OUTS() {}

template <class Head, class... Tail>

void OUTS(Head&& head, Tail&&... tail) {

  cout << head << " \n"[sizeof...(tail)==0];

  OUTS(forward<Tail>(tail)...);

}



template <class T>

void OUTS(vector<T> &vec) { for (auto &e : vec) cout << e << " \n"[&e==&vec.back()]; }



template <class T>

void OUTS(vector<vector<T>> &df) { for (auto &vec : df) OUTS(vec); }



// OUTL

void OUTL() {}

template <class Head, class... Tail>

void OUTL(Head&& head, Tail&&... tail) {

  cout << head << "\n";

  OUTL(forward<Tail>(tail)...);

}



template <class T>

void OUTL(vector<T> &vec) { for (auto &e : vec) cout << e << "\n"; }



// OUTN

void OUTN() {}

template <class Head, class... Tail>

void OUTN(Head&& head, Tail&&... tail) {

  cout << head;

  OUTN(forward<Tail>(tail)...);

}



template <class T>

void OUTN(vector<T> &vec) { for (auto &e : vec) cout << e; }

// }}} End



inline bool inside(int x, int y, int w, int h) {

  return (x >= 0 && y >= 0 && x < w && y < h);

}



constexpr int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};

constexpr int dy[] = {0, 1, 0, -1, -1, 1, 1, -1};



int h, w;



vector<string> mat(1005);

vector<vector<int>> dist(1005, vector<int>(1005, INF));



signed main()

{

  ios::sync_with_stdio(false);

  cin.tie(nullptr);



  IN(h, w);

  rep(i, h) IN(mat[i]);



  queue<pii> que;



  rep(i, h) rep(j, w) {

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

      que.emplace(i, j);

      dist[i][j] = 0;

    }

  }



  i64 res = 0;

  while (!que.empty()) {

    int y = que.front().first;

    int x = que.front().second;

    que.pop();



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

      int ny = y + dy[i];

      int nx = x + dx[i];



      if (inside(nx, ny, w, h) &&

          dist[ny][nx] > dist[y][x] + 1 &&

          mat[ny][nx] != '#') {



        int norm = dist[y][x] + 1;

        mat[ny][nx] = '#';

        chmin(dist[ny][nx], norm);

        chmax(res, dist[ny][nx]);

        que.emplace(ny,nx);

      }

    }

  }



  OUTL(res);



  return 0;

}


// Optimized solution to the same problem (faster):
#include "bits/stdc++.h"

#pragma GCC optimize("Ofast")



// Begin {{{

using namespace std;



#ifndef DEBUG

#define dump(...)

#endif



template <class A, class B> inline bool chmax(A &a, const B &b) { return b > a && (a = b, true); }

template <class A, class B> inline bool chmin(A &a, const B &b) { return b < a && (a = b, true); }



template <class T>

inline vector<T> make_v(const T &initvalue, size_t sz) {

    return vector<T>(sz, initvalue);

}



template <class T, class... Args>

inline auto make_v(const T &initvalue, size_t sz, Args... args) {

    return vector<decltype(make_v<T>(initvalue, args...))>(sz, make_v<T>(initvalue, args...));

}



constexpr int INF = 0x3f3f3f3f;

constexpr int64_t LINF = 0x3f3f3f3f3f3f3f3fLL;

// }}} End



constexpr int dy[] = {0, 1, 0, -1, -1, 1, 1, -1};

constexpr int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};



inline bool inside(int y, int x, int H, int W) {

    return (y >= 0 && x >= 0 && y < H && x < W);

}



signed main() {

    ios_base::sync_with_stdio(false);

    cin.tie(nullptr);



    size_t H, W; cin >> H >> W;



    queue<pair<int, int>> que;

    auto dist = make_v(INF, H, W);



    vector<string> mat(H);

    for (size_t i = 0; i < H; ++i) {

        cin >> mat[i];

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

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

                que.emplace(i, j);

                dist[i][j] = 0;

            }

        }

    }



    int res = 0;

    while (!que.empty()) {

        int y = que.front().first;

        int x = que.front().second;

        que.pop();

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

            int ny = y + dy[i];

            int nx = x + dx[i];

            if (inside(ny, nx, H, W) && chmin(dist[ny][nx], dist[y][x] + 1) && mat[ny][nx] != '#') {

                que.emplace(ny, nx);

                chmax(res, dist[ny][nx]);

            }

        }

    }



    cout << res << "\n";



    return 0;

}


// Fastest known solution for this problem: