fn main() {
let (h, w): (usize, usize) = read_tuple();
let pic: Vec<Vec<char>> = read_mat(h);
let is_adj_all = |i,j| {
let h = h as isize;
let w = w as isize;
let i = i as isize;
let j = j as isize;
let neighbor = [(i-1,j-1),(i-1,j),(i-1,j+1),(i,j-1),(i,j+1),(i+1,j-1),(i+1,j),(i+1,j+1)];
neighbor.iter().filter(|&&(x,y)| 0<=x && x<h && 0<=y && y<w).all(|&(x,y)| pic[x as usize][y as usize]=='#')
};
let mut buf1 = pic.clone();
for i in 0 .. h {
for j in 0 .. w {
if buf1[i][j] == '#' && is_adj_all(i,j) {continue}
buf1[i][j] = '.'
}
}
let is_adj_any = |i,j| {
let h = h as isize;
let w = w as isize;
let i = i as isize;
let j = j as isize;
let neighbor = [(i-1,j-1),(i-1,j),(i-1,j+1),(i,j-1),(i,j+1),(i+1,j-1),(i+1,j),(i+1,j+1)];
neighbor.iter().filter(|&&(x,y)| 0<=x && x<h && 0<=y && y<w).any(|&(x,y)| buf1[x as usize][y as usize]=='#')
};
let mut buf2 = buf1.clone();
for i in 0 .. h {
for j in 0 .. w {
if buf1[i][j] == '#' || is_adj_any(i,j) {
buf2[i][j] = '#'
}
}
}
if pic == buf2 {
println!("possible");
print_mat(&buf1, "");
} else {
println!("impossible");
}
}
fn read_tuple<T1: std::str::FromStr, T2: std::str::FromStr>() -> (T1, T2) {
let mut buf = String::new();
std::io::stdin().read_line(&mut buf).ok();
let mut it = buf.trim().split_whitespace();
let x = it.next().unwrap().parse::<T1>().ok().unwrap();
let y = it.next().unwrap().parse::<T2>().ok().unwrap();
(x, y)
}
fn read_vec() -> Vec<char> {
let mut buf = String::new();
std::io::stdin().read_line(&mut buf).ok();
buf.trim().chars().collect()
}
fn read_mat(h: usize) -> Vec<Vec<char>> {
let mut mat: Vec<Vec<char>> = vec![];
for _ in 0 .. h {
mat.push(read_vec());
}
mat
}
fn print_vec<T: std::string::ToString>(vec: &Vec<T>, sep: &str) {
let out = vec.iter().map(|e| e.to_string()).collect::<Vec<_>>().as_slice().join(sep);
println!("{}", out);
}
fn print_mat<T: std::string::ToString>(mat: &Vec<Vec<T>>, sep: &str) {
for v in mat {
print_vec(v, sep);
}
}