const S4: [&'static str; 4] = ["aabc", "ddbc", "efgg", "efhh"];
const S5: [&'static str; 5] = ["aabbc", "dde.c", "ffegg", "..hij", "..hij"];
const S6: [&'static str; 6] = ["aabbcc", "ddeeff", "ghi...", "ghi...", "...jkl", "...jkl"];
const S7: [&'static str; 7] = [
    "aabbcc.", "ddeef..", "gg..fhh", "..ij..k", "..ij..k", "....lmn", "....lmn",
];

fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());

    let n: usize = sc.read();
    if n == 2 {
        println!("-1");
        return;
    }
    if n == 3 {
        println!("aab");
        println!("c.b");
        println!("cdd");
        return;
    }
    let mut board = vec![vec!['.'; n]; n];
    let r = n % 4 + 4;
    let repeats = (n - r) / 4;
    for k in 0..repeats {
        for i in 0..4 {
            let s: Vec<_> = S4[i].chars().collect();
            for j in 0..4 {
                board[k * 4 + i][k * 4 + j] = s[j];
            }
        }
    }

    for i in 0..r {
        let s: Vec<_> = match r {
            4 => S4[i].chars().collect(),
            5 => S5[i].chars().collect(),
            6 => S6[i].chars().collect(),
            7 => S7[i].chars().collect(),
            _ => unreachable!(),
        };
        for j in 0..r {
            board[repeats * 4 + i][repeats * 4 + j] = s[j];
        }
    }

    for i in 0..n {
        for j in 0..n {
            print!("{}", board[i][j]);
        }
        println!();
    }
}

fn dfs(k: u32, board: &mut Vec<Vec<u8>>, pos: (usize, usize), depth: u8) -> bool {
    let n = board.len();
    let (i, j) = pos;
    if j == 0 {
        for i in 0..i {
            let mut set: u32 = 0;
            for j in 0..n {
                set |= 1 << (board[i][j] as u32);
            }
            set >>= 1;
            if set.count_ones() != k {
                return false;
            }
        }
    }
    if i == n {
        for j in 0..n {
            let mut set: u32 = 0;
            for i in 0..n {
                set |= 1 << (board[i][j] as u32);
            }
            set >>= 1;
            if set.count_ones() != k {
                return false;
            }
        }
        return true;
    }

    let next_pos = if j + 1 == n { (i + 1, 0) } else { (i, j + 1) };

    if j + 1 < n && board[i][j] == 0 && board[i][j + 1] == 0 {
        board[i][j] = depth;
        board[i][j + 1] = depth;

        if dfs(k, board, next_pos, depth + 1) {
            return true;
        }
        board[i][j] = 0;
        board[i][j + 1] = 0;
    }
    if i + 1 < n && board[i][j] == 0 && board[i + 1][j] == 0 {
        board[i][j] = depth;
        board[i + 1][j] = depth;
        if dfs(k, board, next_pos, depth + 1) {
            return true;
        }
        board[i][j] = 0;
        board[i + 1][j] = 0;
    }
    if dfs(k, board, next_pos, depth) {
        true
    } else {
        false
    }
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> Self {
        IO(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: ToString>(&mut self, s: S) {
        use std::io::Write;
        self.1.write(s.to_string().as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}


Measured memory_bytes: 9340