### BUGGY CODE ###

## coding: UTF-8
from decimal import *
from itertools import permutations, combinations,combinations_with_replacement,product
import math
#from math import gcd 旧環境でこれを有効化するとREを吐きます
 
s = input().split()
p = [int(w) for w in s] #これで勝手にNまで拾ってくれます
H = p[0]
W = p[1]
 
a = []
for i in range(H):
    a.append(input())
 
 
#白ベースで最寄りの黒を探す方針
#パディングは'.'でも'#'でもないもので埋める
b = ''
for i in range(W+2):
    b += 'w'
#print(b)
#上と下と右と左に空きマスを挿入する
a.insert(0, b)
for i in range(1, 1+H):
    a[i] = 'w' + a[i] + 'w'
a.append(b)
 
 
header = ' '
for i in range(len(a[0])):
    header += ('{}'.format(i))
 
c=[]
for i in range(H+2):
    c.append([])
 
for i in range(H+2):
    for j in range(W+2):
        c[i].append(a[i][j])
 
 
def see_banmen():
    print(header)
    for i in range(len(c)):
        print('{}{}'.format(i,''.join(c[i])))
#see_banmen()
 
 
 
#queue = [start]
next_list = [] #次の歩数で探すものを格納しておく
step = 1
#mode = 0
#answer_mode = 0
status = True #ゴール判定でゴールについていたらFalseにする
#answer = -1
 
queue = []
for i in range(H+2):
    for j in range(W+2):
        if(c[i][j] == '#'):
            queue.append([i, j])
 
while status:
    if(len(queue) > 0):
        pivot = queue.pop() #軸足はqueueの先頭
        x = pivot[0]
        y = pivot[1]
        if(c[x+1][y] == '.'):
            c[x+1][y] = str(step)
            next_list.append([x+1, y])
        if(c[x-1][y] == '.'):
            c[x-1][y] = str(step)
            next_list.append([x-1, y])
        if(c[x][y+1] == '.'):
            c[x][y+1] = str(step)
            next_list.append([x, y+1])
        if(c[x][y-1] == '.'):
            c[x][y-1] = str(step)
            next_list.append([x, y-1])
    else:
        #queueの中身が空っぽになった
        #基本的にはstep += 1
        if(len(next_list) > 0):
            #next_listの中身がある場合（まだ探索が終了していない場合）
            #next_list -> queue にして next_listはからにする
            for i in range(len(next_list)):
                queue.append(next_list.pop(0))
            next_list = []
            #print()
            #print('step{}end'.format(step))
            #see_banmen()
            #次の探索に移る
            step += 1
        else:
            #初めてnext_listの中身がなくなった場合（探索は終了したい）
            #もう進めない
            #print()
            #print('もう進めない')
            #print('step{}end'.format(step))
            #see_banmen()
            status = False
 
print(step - 1)
            

### FIXED CODE ###

## coding: UTF-8


H,W = map(int,input().split())

c = []
for i in range(H):
    c.append(input())

fresh = [True] * (H*W)
#print(fresh)


queue = []
n = []
for i in range(H):
    for j in range(W):
        if(c[i][j] == '#'):
            fresh[i*W+j] = False
            queue.append(i*W+j)
#print('initial')
#print('fresh:{}'.format(fresh))
#print('queue:{}'.format(queue))

step = 0
status = True
while status:
    if(len(queue)>0):
        #処理を行う
        pivot = queue.pop()
        #print('pivot:{}, queue:{}, n:{}'.format(pivot, queue, n))        
        #右へ移動
        if(pivot%W != W-1 and fresh[pivot+1]):
            n.append(pivot+1)
            fresh[pivot+1] = False
        #左へ移動
        if(pivot%W != 0 and fresh[pivot-1]):
            n.append(pivot-1)
            fresh[pivot-1] = False
        #下へ移動
        if( int(pivot/W)<(H-1) and fresh[pivot+W]):
            n.append(pivot+W)
            fresh[pivot+W] = False
        #上へ移動
        if( int(pivot/W)>0 and fresh[pivot-W] ):
            n.append(pivot-W)
            fresh[pivot-W] = False
        #print('pivot:{}, queue:{}, n:{}'.format(pivot, queue, n))
    elif(len(n)>0):
        queue = n
        n = []
        #歩数を増やそう
        step += 1
        #print('step{}end,queue:{}, n:{}'.format(step, queue, n))
    else:
        status = False


print(step)