Problem:
Score : 200 points

Problem Statement

You are given an H × W grid.

The squares in the grid are described by H strings, S_1,...,S_H.

The j-th character in the string S_i corresponds to the square at the i-th row from the top and j-th column from the left (1 \leq i \leq H,1 \leq j \leq W).

. stands for an empty square, and # stands for a square containing a bomb.

Dolphin is interested in how many bomb squares are horizontally, vertically or diagonally adjacent to each empty square.

(Below, we will simply say "adjacent" for this meaning. For each square, there are at most eight adjacent squares.)

He decides to replace each . in our H strings with a digit that represents the number of bomb squares adjacent to the corresponding empty square.

Print the strings after the process.

Constraints

1 \leq H,W \leq 50

S_i is a string of length W consisting of # and ..

Input

Input is given from Standard Input in the following format:

H W
S_1
:
S_H

Output

Print the H strings after the process.

The i-th line should contain a string T_i of length W, where the j-th character in T_i corresponds to the square at the i-th row from the top and j-th row from the left in the grid (1 \leq i \leq H, 1 \leq j \leq W).

Sample Input 1

3 5
.....
.#.#.
.....

Sample Output 1

11211
1#2#1
11211

For example, let us observe the empty square at the first row from the top and first column from the left.

There is one bomb square adjacent to this empty square: the square at the second row and second column.

Thus, the . corresponding to this empty square is replaced with 1.

Sample Input 2

3 5
#####
#####
#####

Sample Output 2

#####
#####
#####

It is possible that there is no empty square.

Sample Input 3

6 6
#####.
#.#.##
####.#
.#..#.
#.##..
#.#...

Sample Output 3

#####3
#8#7##
####5#
4#65#2
#5##21
#4#310

Solution in Haskell (GHC 7.10.3) (judge verdict: Accepted)

import Control.Monad
import Data.Array
import qualified Data.ByteString.Char8 as BS
import Data.Maybe

readInt = fst . fromJust . BS.readInt
readIntList = map readInt . BS.words
readString = map BS.unpack . BS.words

getIntList = readIntList <$> BS.getLine
getString = readString <$> BS.getLine
getNString n = map readString <$> replicateM n BS.getLine

getNeibor :: Int -> Int -> Int -> Int -> [[Int]]
getNeibor w' h' w h = do
  let hs
        | h' == 1 = [h', h' + 1]
        | h' == h = [h' - 1, h']
        | otherwise = [h' - 1, h', h' + 1]
  let ws
        | w' == 1 = [w', w' + 1]
        | w' == w = [w' - 1, w']
        | otherwise = [w' - 1, w', w' + 1]
  filter (\x -> x /= [h', w']) (sequence [hs, ws])

sumBomb :: Array (Int, Int) Char -> [[Int]] -> Int
sumBomb sss [] = 0
sumBomb sss (ns : nss)
  | rc == '#' = 1 + sumBomb sss nss
  | otherwise = sumBomb sss nss
  where
    rc = sss ! (head (ns), last (ns))

calc sss h w i = do
  let i' = i + 1
  let h' = i' `div` w
  let w' = i' `mod` w
  let w''
        | w' == 0 = w
        | otherwise = w'
  let h''
        | w' == 0 = h'
        | otherwise = h' + 1
  if sss ! (h'', w'') == '#'
    then putStr "#"
    else do
      let nss = getNeibor w'' h'' w h
      putStr $ show (sumBomb sss nss)
  if w'' == w
    then do
      putStr "\n"
      when (i' /= h * w) $ calc sss h w (i + 1)
    else calc sss h w (i + 1)

calcable :: String -> [Int]
calcable [] = []
calcable (s : ss)
  | s == '#' = 1 : calcable ss
  | otherwise = 0 : calcable ss

calcSingle :: Array Int Int -> Int -> Int -> String
calcSingle ss n' n
  | n' == (n + 1) = []
  | otherwise = v ++ calcSingle ss (n' + 1) n
  where
    v
      | ss ! n' == 1 = "#"
      | n' == 1 = show $ ss ! 2
      | n' == n = show $ ss ! (n - 1)
      | otherwise = show $ (ss ! (n' - 1)) + (ss ! (n' + 1))

putCharLn :: Char -> IO()
putCharLn c = putStrLn $ [c]

main = do
  [h, w] <- getIntList
  if h == 1
    then do
      [sss] <- getString
      if w == 1
        then if sss == "#" then putStrLn "#" else putStrLn "0"
        else do
          let sss' = calcable sss
          let sss'' = listArray (1, w) sss'
          putStrLn $ calcSingle sss'' 1 w
    else do
      if w == 1
        then do
          sss <- getNString h
          let sss' = calcable (concat (map head sss))
          let sss'' = listArray (1, h) sss'
          let result = calcSingle sss'' 1 h
          mapM_ putCharLn result
          putStr "\n"
        else do
          sss <- getNString h
          let sss' = concat (map head sss)
          let sss'' = listArray ((1, 1), (h, w)) sss'
          calc sss'' h w 0