### BUGGY CODE ###

from bisect import bisect_left, bisect_right
from collections import Counter, defaultdict, deque, OrderedDict
from copy import deepcopy
from fractions import gcd
from functools import lru_cache, reduce
from math import ceil, floor
from sys import setrecursionlimit

import heapq as hq
import itertools as its
import operator as op


# globals
inf = float('inf')
H, W = 0, 0
A = []


def set_inputs():
    global H, W, A
    H, W = get_li()
    A = get_data(H, [str])
    return


def main():
    setrecursionlimit(100000)
    set_inputs()
    # ----------MAIN----------
    remaining = set()
    completed = set()
    for i, ai_ in enumerate(A):
        for j, a in enumerate(ai_):
            if a == ".":
                continue
            if i > 0 and A[i-1][j] == "#" and i < H - 1 and A[i+1][j] == "#" and j > 0 and A[i][j-1] == "#" and j < W - 1 and A[i][j+1] == "#":
                completed.add((i, j))
                continue
            remaining.add((i, j))
    ans = 0
    while remaining:
        _next = set()
        for (i, j) in remaining:
            completed.add((i, j))
            if i > 0 and (i-1, j) not in completed and (i-1, j) not in remaining:
                _next.add((i-1, j))
            if i < H - 1 and (i+1, j) not in completed and (i+1, j) not in remaining:
                _next.add((i+1, j))
            if j > 0 and (i, j-1) not in completed and (i, j-1) not in remaining:
                _next.add((i, j-1))
            if j < W - 1 and (i, j+1) not in completed and (i, j+1) not in remaining:
                _next.add((i, j+1))
        remaining = _next
        ans += 1
    print(max(ans - 1, 0))
    return


def get_int():
    return int(input())


def get_float():
    return float(input())


def get_str():
    return input().strip()


def get_li():
    return [int(i) for i in input().split()]


def get_lf():
    return [float(f) for f in input().split()]


def get_lc():
    return list(input().strip())


def get_data(n, types, sep=None):
    if len(types) == 1:
        return [types[0](input().strip()) for _ in range(n)]
    return list(zip(*(
        [t(x) for t, x in zip(types, input().strip().split(sep=sep))]
        for _ in range(n)
    )))


if __name__ == '__main__':
    main()


### FIXED CODE ###

from bisect import bisect_left, bisect_right
from collections import Counter, defaultdict, deque, OrderedDict
from copy import deepcopy
from fractions import gcd
from functools import lru_cache, reduce
from math import ceil, floor
from sys import setrecursionlimit

import heapq as hq
import itertools as its
import operator as op


# globals
inf = float('inf')
H, W = 0, 0
A = []


def set_inputs():
    global H, W, A
    H, W = get_li()
    A = [get_str() for _ in range(H)]
    return


def main():
    set_inputs()
    # ----------MAIN----------
    stage = [[0 for _ in range(W)] for _ in range(H)]
    remaining = deque()
    for i, ai_ in enumerate(A):
        for j, a in enumerate(ai_):
            if a == ".":
                continue
            stage[i][j] = 1
            remaining.append((i, j))
    ans = 0
    while remaining:
        _next = deque()
        for (i, j) in remaining:
            stage[i][j] = 2
            if i > 0 and stage[i-1][j] == 0:
                stage[i-1][j] = 1
                _next.append((i-1, j))
            if i < H - 1 and stage[i+1][j] == 0:
                stage[i+1][j] = 1
                _next.append((i+1, j))
            if j > 0 and stage[i][j-1] == 0:
                stage[i][j-1] = 1
                _next.append((i, j-1))
            if j < W - 1 and stage[i][j+1] == 0:
                stage[i][j+1] = 1
                _next.append((i, j+1))
        remaining = _next
        ans += 1
    if ans == 0:
        print(0)
    else:
        print(ans - 1)
    return


def get_int():
    return int(input())


def get_float():
    return float(input())


def get_str():
    return input().strip()


def get_li():
    return [int(i) for i in input().split()]


def get_lf():
    return [float(f) for f in input().split()]


def get_lc():
    return list(input().strip())


def get_data(n, types, sep=None):
    if len(types) == 1:
        return [types[0](input().strip()) for _ in range(n)]
    return list(zip(*(
        [t(x) for t, x in zip(types, input().strip().split(sep=sep))]
        for _ in range(n)
    )))


if __name__ == '__main__':
    main()