from collections import deque







def bfs(maze, visited, queue, H, W):

    count = 0

    while queue:

        y, x = queue.popleft()

        for i, j in ([1, 0], [-1, 0], [0, 1], [0, -1]):

            new_y, new_x = y + i, x + j

            if -1 < new_y < H and -1 < new_x < W:

                if maze[new_y][new_x] == "." and visited[new_y][new_x] == -1:

                    visited[new_y][new_x] = visited[y][x] + 1

                    queue.append([new_y, new_x])



    ans = -1

    for i in range(H):

        for j in range(W):

            ans = max(ans,visited[i][j])

    return ans



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



maze = [eval(input()) for i in range(H)]

visited = [[-1] * W for i in range(H)]



queue = deque([])

for i in range(H):

    for j in range(W):

        if maze[i][j] == "#":

            visited[i][j] = 0

            queue.append([i, j])



print((bfs(maze, visited, queue, H, W)))
H, W = list(map(int, input().split()))

maze = [eval(input()) for _ in range(H)]

seen = [[-1] * W for _ in range(H)]



from collections import deque





queue = deque()

for i in range(H):

    for j in range(W):

        if maze[i][j] == '#':

            queue.append([i, j, 0])

            seen[i][j] = 0



def bfs(maze, seen):

    while queue:

        y, x, c = queue.popleft()

        for i, j in [1, 0], [-1, 0], [0, 1], [0, -1]:

            dy = y + i

            dx = x + j

            if dy < 0 or H <= dy or dx < 0 or W <= dx:

                continue

            if seen[dy][dx] > -1:

                continue

            if maze[dy][dx] == '#':

                continue

            seen[dy][dx] = c + 1

            queue.append([dy, dx, c+1])



def check_max(seen):

    ans = 0

    for i in range(H):

        for j in range(W):

            ans = max(ans, seen[i][j])

    return ans

    

bfs(maze, seen)

print((check_max(seen)))
from collections import deque


def bfs(maze, visited, queue, H, W):
    count = 0
    while queue:
        y, x = queue.popleft()
        for i, j in ([1, 0], [-1, 0], [0, 1], [0, -1]):
            new_y, new_x = y + i, x + j
            if -1 < new_y < H and -1 < new_x < W:
                if maze[new_y][new_x] == "." and visited[new_y][new_x] == -1:
                    visited[new_y][new_x] = visited[y][x] + 1
                    queue.append([new_y, new_x])
    ans = -1
    for i in range(H):
        for j in range(W):
            ans = max(ans, visited[i][j])
    return ans


H, W = list(map(int, input().split()))
maze = [eval(input()) for i in range(H)]
visited = [[-1] * W for i in range(H)]
queue = deque([])
for i in range(H):
    for j in range(W):
        if maze[i][j] == "#":
            visited[i][j] = 0
            queue.append([i, j])
print((bfs(maze, visited, queue, H, W)))

H, W = list(map(int, input().split()))
maze = [eval(input()) for _ in range(H)]
seen = [[-1] * W for _ in range(H)]
from collections import deque

queue = deque()
for i in range(H):
    for j in range(W):
        if maze[i][j] == "#":
            queue.append([i, j, 0])
            seen[i][j] = 0


def bfs(maze, seen):
    while queue:
        y, x, c = queue.popleft()
        for i, j in [1, 0], [-1, 0], [0, 1], [0, -1]:
            dy = y + i
            dx = x + j
            if dy < 0 or H <= dy or dx < 0 or W <= dx:
                continue
            if seen[dy][dx] > -1:
                continue
            if maze[dy][dx] == "#":
                continue
            seen[dy][dx] = c + 1
            queue.append([dy, dx, c + 1])


def check_max(seen):
    ans = 0
    for i in range(H):
        for j in range(W):
            ans = max(ans, seen[i][j])
    return ans


bfs(maze, seen)
print((check_max(seen)))

+H, W = list(map(int, input().split())) +maze = [eval(input()) for _ in range(H)] +seen = [[-1] * W for _ in range(H)] +queue = deque() +for i in range(H): +    for j in range(W): +        if maze[i][j] == "#": +            queue.append([i, j, 0]) +            seen[i][j] = 0 -def bfs(maze, visited, queue, H, W): -    count = 0 + +def bfs(maze, seen): -        y, x = queue.popleft() -        for i, j in ([1, 0], [-1, 0], [0, 1], [0, -1]): -            new_y, new_x = y + i, x + j -            if -1 < new_y < H and -1 < new_x < W: -                if maze[new_y][new_x] == "." and visited[new_y][new_x] == -1: -                    visited[new_y][new_x] = visited[y][x] + 1 -                    queue.append([new_y, new_x]) -    ans = -1 +        y, x, c = queue.popleft() +        for i, j in [1, 0], [-1, 0], [0, 1], [0, -1]: +            dy = y + i +            dx = x + j +            if dy < 0 or H <= dy or dx < 0 or W <= dx: +                continue +            if seen[dy][dx] > -1: +                continue +            if maze[dy][dx] == "#": +                continue +            seen[dy][dx] = c + 1 +            queue.append([dy, dx, c + 1]) + + +def check_max(seen): +    ans = 0 -            ans = max(ans, visited[i][j]) +            ans = max(ans, seen[i][j]) -H, W = list(map(int, input().split())) -maze = [eval(input()) for i in range(H)] -visited = [[-1] * W for i in range(H)] -queue = deque([]) -for i in range(H): -    for j in range(W): -        if maze[i][j] == "#": -            visited[i][j] = 0 -            queue.append([i, j]) -print((bfs(maze, visited, queue, H, W))) +bfs(maze, seen) +print((check_max(seen)))