use std::cmp;
use std::collections::HashSet;

macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

#[inline]
pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
    debug_assert!(min <= max, "min must be less than or equal to max");
    if input < min {
        min
    } else if input > max {
        max
    } else {
        input
    }
}

#[allow(dead_code)]
fn practice_1() {
    input! {
    n: i32,
    m: [i32; 2],
    s: chars,
    }
    let s: Vec<char> = s;
    let s: String = s.into_iter().collect();

    println!("{} {}", n + m[0] + m[1], s);
}

#[allow(dead_code)]
fn abc086_a() {
    input! {
    n: [i32; 2],
    }
    let prod: i32 = n[0] * n[1];
    let res = if prod % 2 == 0 {
        "Even"
    } else {
        "Odd"
    };
    println!("{}", res)
}

#[allow(dead_code)]
fn abc081_a() {
    input! {
    s: chars,
    }
    let s: Vec<char> = s;
    let res: u32 = s.iter().map(|n| n.to_digit(10).unwrap()).sum();

    println!("{}", res)
}

#[allow(dead_code)]
fn abc081_b() {
    input! {
    n: i32,
    arr: [i32; n],
    }
    let mut arr: Vec<i32> = arr;
    let mut cnt = 0;

    loop {
        if arr.iter().any(|v| (v % 2) == 1) {
            break;
        }
        arr = arr.iter().map(|v| v / 2).collect();
        cnt += 1;
    }

    println!("{}", cnt)
}

#[allow(dead_code)]
fn abc083_b() {
    input! {
    arr: [i32; 3],
    }

    let n: i32 = arr[0];
    let a: i32 = arr[1];
    let b: i32 = arr[2];

    let (vals, _total): (Vec<i32>, Vec<i32>) = (0..n + 1)
        .map(|i| {
            let d0 = i - (i / 10) * 10;
            let d1 = (i / 10) - (i / 100) * 10;
            let d2 = (i / 100) - (i / 1000) * 10;
            let d3 = (i / 1000) - (i / 10000) * 10;
            let d4 = (i / 10000) - (i / 100000) * 10;
            (i, d0 + d1 + d2 + d3 + d4)
        })
        .filter(|&(_i, total)| {
            (a <= total) && (total <= b)
        })
        .unzip();
//        .for_each(|(i, _total)| {
//            res += i;
//        });
    let res: i32 = vals.iter().sum();

    println!("{:?}", res)
}

#[allow(dead_code)]
fn abc087_b() {
    input! {
    n_500: i32,
    n_100: i32,
    n_50: i32,
    total: i32,
    }

    let n_500: i32 = n_500;
    let n_100: i32 = n_100;
    let n_50: i32 = n_50;
    let total: i32 = total;
    let mut cnt = 0;

    for i in 0..n_500 + 1 {
        for j in 0..n_100 + 1 {
            for k in 0..n_50 + 1 {
                let total_tried = i * 500 + j * 100 + k * 50;
                if total_tried == total {
//                    println!("{}, {}, {}", i, j, k);
                    cnt += 1;
                }
            }
        }
    }

    println!("{}", cnt)
}

#[allow(dead_code)]
fn abc088_b() {
    input! {
    n_items: i32,
    arr: [i32; n_items],
    }

    let mut arr: Vec<i32> = arr;
    arr.sort();

    let res: i32 = arr.iter().rev()
        .enumerate()
        .map(|(i, &v)| {
            if (i % 2) == 0 {
                v
            } else {
                -v
            }
        })
        .sum();

    println!("{:?}", res)
}

#[allow(dead_code)]
fn abc085_b() {
    input! {
    n_: usize,
    arr: [[i32; 1]; n_],
    }

    let arr: Vec<Vec<i32>> = arr;
    let res = arr.iter()
//        .flatten()
        .flat_map(|a| a)
        .cloned()
        .collect::<HashSet<i32>>()
        .len();

    println!("{:?}", res)
}

#[allow(dead_code)]
fn abc085_c() {
    input! {
    args: [u32; 2],
    }

    let n: u32 = args[0];
    let total: u32 = args[1];

    let x_max = cmp::min(total / 10_000, n) + 1;

    for x in (0..x_max).rev() {
        if x * 10_000 > total { break; }
        let y_max = cmp::min(total / 5_000, n - x) + 1;
        for y in (0..y_max).rev() {
            let z = n - x - y;
            if x * 10_000 + y * 5_000 + z * 1_000 == total {
                println!("{} {} {}", x, y, z);
                return;
            }
        }
    }

    println!("-1 -1 -1")
}


#[allow(dead_code)]
fn arc065_a() {
    input! {
    arr: chars,
    }
    let mut arr: Vec<char> = arr;

    let dream = vec!['d', 'r', 'e', 'a', 'm'];
    let dreamer = vec!['d', 'r', 'e', 'a', 'm', 'e', 'r'];
    let erase = vec!['e', 'r', 'a', 's', 'e'];
    let eraser = vec!['e', 'r', 'a', 's', 'e', 'r'];

    fn rel(n: i32) -> usize {
        if n < 0 {
            0
        } else {
            n as usize
        }
    }

    loop {
        let size = arr.len() as i32;
        if size == 0 {
            println!("YES");
            return;
        }

        let last_5 = rel(size - 5);
        let last_6 = rel(size - 6);
        let last_7 = rel(size - 7);

        let is_dream = arr[last_5..].to_vec() == dream;
        let is_dreamer = arr[last_7..].to_vec() == dreamer;
        let is_erase = arr[last_5..].to_vec() == erase;
        let is_eraser = arr[last_6..].to_vec() == eraser;

        if is_dream {
            arr.drain(last_5..);
        } else if is_dreamer {
            arr.drain(last_7..);
        } else if is_erase {
            arr.drain(last_5..);
        } else if is_eraser {
            arr.drain(last_6..);
        } else {
            println!("NO");
            return;
        }
    }
}

#[allow(dead_code)]
fn arc089_a() {
    input! {
    n_: usize,
    arr: [[u32; 3]; n_],
    }

    let arr: Vec<Vec<u32>> = arr;

    for a in arr {
        let t = a[0];
        let x = a[1];
        let y = a[2];

        // Check dist
        if x + y > t {
            println!("No");
            return;
        }

        if ((x + y) % 2) == 0 && (t % 2) == 0 {
            continue;
        }

        if ((x + y) % 2) == 1 && (t % 2) == 1 {
            continue;
        }

        println!("No");
        return;
    }

    println!("Yes");
}

#[allow(dead_code)]
fn abc075_b() {
    input! {
        h: usize,
        w: usize,
        board: [chars; h],
    }
    let h = h as i32;
    let w = w as i32;

    let board: Vec<Vec<char>> = board;

    for r in 0..h {
        for c in 0..w {
//            println!("{} {}", r, c);

            if board[r as usize][c as usize] == '#' {
                print!("#");
                continue;
            }

            let r_min = clamp(r - 1, 0, h) as usize;
            let r_max = clamp(r + 2, 0, h) as usize;
            let c_min = clamp(c - 1, 0, w) as usize;
            let c_max = clamp(c + 2, 0, w) as usize;

            let mut total = 0;

            for r_tmp in r_min..r_max {
                for c_tmp in c_min..c_max {
                    let val = board[r_tmp][c_tmp];
//                    println!("{} {} {} {} {}", val, r_min, r_max, c_min, c_max);
                    if val == '#' {
                        total += 1;
                    }
                }
            }

            let res = total.to_string();
            print!("{}", res);
        }
        println!("");
    }
}

fn main() {
    abc075_b()
}



Measured memory_bytes: 4352