input: def solve_sudoku(board):
      """ Solve any solvable Sudoku puzzle by filling the blank cells represented as '0'
      with digits from 1 to 9 according to following constraints:
      1. Each of the digits 1-9 must occur exactly once in each row.
      2. Each of the digits 1-9 must occur exactly once in each column.
      3. Each of the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.
      
      Output the completed grid if solvable, otherwise print "No solution" if the puzzle is unsolvable.
      
      >>> board1 = [
      ...     [7,8,0,4,0,0,1,2,0],
      ...     [6,0,0,0,7,5,0,0,9],
      ...     [0,0,0,6,0,1,0,7,8],
      ...     [0,0,7,0,4,0,2,6,0],
      ...     [0,0,1,0,5,0,9,3,0],
      ...     [9,0,4,0,6,0,0,0,5],
      ...     [0,7,0,3,0,0,0,1,2],
      ...     [1,2,0,0,0,7,4,0,0],
      ...     [0,4,9,2,0,6,0,0,7]
      ... ]
      >>> solve_sudoku(board1) # Assuming the board is solvable, it will fill out the grid
      [[7, 8, 5, 4, 3, 9, 1, 2, 6],
       [6, 1, 2, 8, 7, 5, 3, 4, 9],
       [4, 9, 3, 6, 2, 1, 5, 7, 8],
       [8, 5, 7, 9, 4, 3, 2, 6, 1],
       [2, 6, 1, 7, 5, 8, 9, 3, 4],
       [9, 3, 4, 1, 6, 2, 7, 8, 5],
       [5, 7, 8, 3, 9, 4, 6, 1, 2],
       [1, 2, 6, 5, 8, 7, 4, 9, 3],
       [3, 4, 9, 2, 1, 6, 8, 5, 7]]
       
      >>> board2 = [
      ...     [7,8,0,4,0,0,1,2,0],
      ...     [6,0,0,0,7,5,0,0,9],
      ...     [0,0,0,6,0,1,0,7,8],
      ...     [0,0,7,0,4,0,2,6,0],
      ...     [0,0,1,0,5,0,9,3,0],
      ...     [9,0,4,0,6,0,0,0,5],
      ...     [0,7,0,3,0,0,0,1,2],
      ...     [1,2,0,0,0,7,4,0,0],
      ...     [0,4,9,2,0,6,0,0,8]
      ... ]
      >>> solve_sudoku(board2) # Assuming the board is unsolvable due to a constraint violation, it will print "No solution"
      No solution
      """
      
      # Utility function to find vacant cells
      # Returns a boolean     
      def find_vacant_cell(board, l):
          for row in range(9): 
              for col in range(9): 
                  if board[row][col] == 0: 
                      l[0] = row 
                      l[1] = col 
                      return True
          return False
  
      # Utility function to check if a number  
      # is not currently placed in a particular  
      # row, column and block 
      def is_safe(board, row, col, num): 
  
          # Check if 'num' is not already placed  
          # in current row, current column  
          # and current 3x3 box 
          for i in range(9):
  
              # Check the rows
              if(board[row][i] == num): 
                  return False
  
              # Check the columns 
              if(board[i][col] == num): 
                  return False
  
              # Check the 3x3 boxes 
              if(board[(row//3)*3 + i//3][(col//3)*3 + i%3] == num): 
                  return False
  
          return True
  
      # Solve the sudoku 
      def solve(board):
          # 'l' is a list variable that keeps 
          # the record of row and col in 
          # find_vacant_cell function 
          l = [0, 0] 
  
          # If there is no unassigned location, 
          # we are done 
          if (not find_vacant_cell(board, l)): 
              return True
  
          # Assigning the list values
          row = l[0] 
          col = l[1] 
  
          # consider digits 1 to 9 
          for num in range(1, 10): 
  
              # if it is a safe position
              if (is_safe(board, row, col, num)): 
  
                  # make tentative assignment 
                  board[row][col] = num 
  
                  # return if succcess
                  if (solve(board)): 
                      return True
  
                  # failure, unmake and try again 
                  board[row][col] = 0
  
          # trigger backtracking 
          return False
  
      # Driver Program 
      if (solve(board)): 
          return board
      else: 
          return "No solution"
output:     # Utility function to find vacant cells
      # Returns a boolean     
      def find_vacant_cell(board, l):
          for row in range(9): 
              for col in range(9): 
                  if board[row][col] == 0: 
                      l[0] = row 
                      l[1] = col 
                      return True
          return False
  
      # Utility function to check if a number  
      # is not currently placed in a particular  
      # row, column and block 
      def is_safe(board, row, col, num): 
  
          # Check if 'num' is not already placed  
          # in current row, current column  
          # and current 3x3 box 
          for i in range(9):
  
              # Check the rows
              if(board[row][i] == num): 
                  return False
  
              # Check the columns 
              if(board[i][col] == num): 
                  return False
  
              # Check the 3x3 boxes 
              if(board[(row//3)*3 + i//3][(col//3)*3 + i%3] == num): 
                  return False
  
          return True
  
      # Solve the sudoku 
      def solve(board):
          # 'l' is a list variable that keeps 
          # the record of row and col in 
          # find_vacant_cell function 
          l = [0, 0] 
  
          # If there is no unassigned location, 
          # we are done 
          if (not find_vacant_cell(board, l)): 
              return True
  
          # Assigning the list values
          row = l[0] 
          col = l[1] 
  
          # consider digits 1 to 9 
          for num in range(1, 10): 
  
              # if it is a safe position
              if (is_safe(board, row, col, num)): 
  
                  # make tentative assignment 
                  board[row][col] = num 
  
                  # return if succcess
                  if (solve(board)): 
                      return True
  
                  # failure, unmake and try again 
                  board[row][col] = 0
  
          # trigger backtracking 
          return False
  
      # Driver Program 
      if (solve(board)): 
          return board
      else: 
          return "No solution"