Buggy python submission (verdict: Time Limit Exceeded):
def solve():
    from sys import stdin
    f_i = stdin
    
    H, W = map(int, f_i.readline().split())
    
    grid = ['W'] * (W + 2)
    for i in range(H):
        grid += ['W'] + list(f_i.readline().rstrip()) + ['W']
    grid += ['W'] * (W + 2)
    
    adj = (1, -1, W + 2, -W - 2)
    cnt = 0
    next_grid = grid[:]
    while True:
        if '.' not in grid:
            print(cnt)
            break
        
        cnt += 1
        
        idx = 0
        while True:
            try:
                idx = grid.index('.', idx)
                for a in adj:
                    adj_pos = idx + a
                    if grid[adj_pos] == '#':
                        next_grid[idx] = '#'
                        break
                idx += 1
            except ValueError:
                break
        
        grid = next_grid[:]

solve()

Fixed submission:
def solve():
    from collections import deque
    from sys import stdin
    f_i = stdin
    
    H, W = map(int, f_i.readline().split())
    
    grid = ['W'] * (W + 2)
    for i in range(H):
        grid += ['W'] + list(f_i.readline().rstrip()) + ['W']
    grid += ['W'] * (W + 2)
    
    q = deque()
    for i, cell in enumerate(grid):
        if cell == '#':
            q.append((i, 0)) # (pos, operation count)
    move = (1, -1, W + 2, -W - 2)
    
    while q:
        pos, count = q.popleft()
        for mv in move:
            next_pos = pos + mv
            if grid[next_pos] == '.':
                grid[next_pos] = '#'
                q.append((next_pos, count + 1))
    
    print(count)
    
solve()

Buggy python submission (verdict: Time Limit Exceeded):
def solve():
    from sys import stdin
    f_i = stdin
    
    H, W = map(int, f_i.readline().split())
    
    grid = ['W'] * (W + 2)
    for i in range(H):
        grid += ['W'] + list(f_i.readline().rstrip()) + ['W']
    grid += ['W'] * (W + 2)
    
    adj = (1, -1, W + 2, -W - 2)
    cnt = 0
    next_grid = grid[:]
    while True:
        if '.' not in grid:
            print(cnt)
            break
        
        cnt += 1
        
        idx = 0
        while True:
            try:
                idx = grid.index('#', idx)
                for a in adj:
                    adj_pos = idx + a
                    if grid[adj_pos] == '.':
                        next_grid[adj_pos] = '#'
                idx += 1
            except ValueError:
                break
        
        grid = next_grid[:]

solve()

Fixed submission:
def solve():
    from collections import deque
    from sys import stdin
    f_i = stdin
    
    H, W = map(int, f_i.readline().split())
    
    grid = ['W'] * (W + 2)
    for i in range(H):
        grid += ['W'] + list(f_i.readline().rstrip()) + ['W']
    grid += ['W'] * (W + 2)
    
    q = deque()
    for i, cell in enumerate(grid):
        if cell == '#':
            q.append((i, 0)) # (pos, operation count)
    move = (1, -1, W + 2, -W - 2)
    
    while q:
        pos, count = q.popleft()
        for mv in move:
            next_pos = pos + mv
            if grid[next_pos] == '.':
                grid[next_pos] = '#'
                q.append((next_pos, count + 1))
    
    print(count)
    
solve()