output_description: Print the number of operations that will be performed.
  
  * * *
input_description: Input is given from Standard Input in the following format:
  
      
      
      H W
      A_{11}A_{12}...A_{1W}
      :
      A_{H1}A_{H2}...A_{HW}
attempt: class Node:
      def __init__(self, data):
          self.data = data
          self.next = None
  
  
  class Queue:
      def __init__(self):
          self.head = None
          self.last = None
          self._size = 0
  
      def enqueue(self, data):
          if self.last is None:
              self.head = Node(data)
              self.last = self.head
          else:
              self.last.next = Node(data)
              self.last = self.last.next
  
          self._size += 1
  
      def dequeue(self):
          if self.head is None:
              return None
          else:
              to_return = self.head.data
              self.head = self.head.next
              self._size -= 1
  
              if self._size == 0:
                  self.head = None
                  self.last = None
              return to_return
  
      def size(self):
          return self._size
  
  
  def inside(y, x, H, W):
      if 0 <= y < H and 0 <= x < W:
          return True
      else:
          return False
  
  
  def addQueueIfPossible(new_y, new_x, new_val, data, queue):
      if inside(new_y, new_x, H, W) and data[new_y][new_x] == -1:
          data[new_y][new_x] = new_val
          queue.enqueue((new_y, new_x, new_val))
          return True
      else:
          return False
  
  
  H, W = map(int, input().split())
  
  data = []
  for _ in range(H):
      data.append([0 if it == "#" else -1 for it in input()])
  
  
  queue = Queue()
  for y in range(H):
      for x in range(W):
          if data[y][x] == 0:
              queue.enqueue((y, x, 0))
  
  while queue.size() > 0:
      y, x, val = queue.dequeue()
      # up
      addQueueIfPossible(y - 1, x, val + 1, data, queue)
      # down
      addQueueIfPossible(y + 1, x, val + 1, data, queue)
      # right
      addQueueIfPossible(y, x + 1, val + 1, data, queue)
      # down
      addQueueIfPossible(y, x - 1, val + 1, data, queue)
  
  print(val)
  
problem_description: Statement
  
  You are given a grid of squares with H horizontal rows and W vertical columns,
  where each square is painted white or black. HW characters from A_{11} to
  A_{HW} represent the colors of the squares. A_{ij} is `#` if the square at the
  i-th row from the top and the j-th column from the left is black, and A_{ij}
  is `.` if that square is white.
  
  We will repeatedly perform the following operation until all the squares are
  black:
  
    * Every white square that shares a side with a black square, becomes black.
  
  Find the number of operations that will be performed. The initial grid has at
  least one black square.
samples: [{"input": "3 3\n    ...\n    .#.\n    ...", "output": "2\n    \n\nAfter one operation, all but the corners of the grid will be black. After one\nmore operation, all the squares will be black.\n\n* * *"}, {"input": "6 6\n    ..#..#\n    ......\n    #..#..\n    ......\n    .#....\n    ....#.", "output": "3"}]