#[allow(unused_imports)]
use std::cmp::{max, min};
#[allow(unused_imports)]
use std::collections::{HashMap, HashSet};

mod util {
    use std::io::stdin;
    use std::str::FromStr;
    use std::fmt::Debug;

    #[allow(dead_code)]
    pub fn line() -> String {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        line.trim().to_string()
    }

    #[allow(dead_code)]
    pub fn get<T: FromStr>() -> T
    where
        <T as FromStr>::Err: Debug,
    {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        line.trim().parse().unwrap()
    }

    #[allow(dead_code)]
    pub fn gets<T: FromStr>() -> Vec<T>
    where
        <T as FromStr>::Err: Debug,
    {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        line.split_whitespace()
            .map(|t| t.parse().unwrap())
            .collect()
    }

    #[allow(dead_code)]
    pub fn get2<T: FromStr, U: FromStr>() -> (T, U)
    where
        <T as FromStr>::Err: Debug,
        <U as FromStr>::Err: Debug,
    {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        let mut iter = line.split_whitespace();
        (
            iter.next().unwrap().parse().unwrap(),
            iter.next().unwrap().parse().unwrap(),
        )
    }

    #[allow(dead_code)]
    pub fn get3<S: FromStr, T: FromStr, U: FromStr>() -> (S, T, U)
    where
        <S as FromStr>::Err: Debug,
        <T as FromStr>::Err: Debug,
        <U as FromStr>::Err: Debug,
    {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        let mut iter = line.split_whitespace();
        (
            iter.next().unwrap().parse().unwrap(),
            iter.next().unwrap().parse().unwrap(),
            iter.next().unwrap().parse().unwrap(),
        )
    }
}


#[allow(unused_macros)]
macro_rules! debug {
    ($x: expr) => {
        println!("{}: {:?}", stringify!($x), $x)
    }
}

fn main() {
    let (h, w): (usize, usize) = util::get2();
    let board: Vec<Vec<bool>> = (0..h)
        .map(|_| util::line().chars().map(|c| c == '#').collect())
        .collect();

    let mut nums = vec![vec![" ".to_owned(); w]; h];
    for i in 0..h as i64 {
        for k in 0..w as i64 {
            if board[i as usize][k as usize] {
                nums[i as usize][k as usize] = "#".to_owned();
            } else {
                let n = [
                    (-1, 0),
                    (-1, 1),
                    (-1, -1),
                    (0, 1),
                    (0, -1),
                    (1, 0),
                    (1, 1),
                    (1, -1),
                ].iter()
                    .filter(|&&(dx, dy)| {
                        (i + dx) >= 0 && (i + dx) < h as i64 && (k + dy) >= 0 && (k + dy) < w as i64
                    })
                    .filter(|&&(dx, dy)| board[(i + dx) as usize][(k + dy) as usize])
                    .count();

                nums[i as usize][k as usize] = n.to_string();
            }
        }
    }

    for i in 0..h {
        println!("{}", nums[i].join(""));
    }
}


Measured memory_bytes: 4352