#[allow(unused_macros)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

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

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

#[allow(unused_macros)]
macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

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

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

    ($next:expr, bytes) => {
        read_value!($next, String).into_bytes()
    };

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

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

fn main() {
    input! {
        n: usize,
    }

    // solve(0, 0, 1, &mut vec![vec![0; n as usize]; n as usize]);

    let sol3 = [b"aa.", b"..b", b"..b"];
    let sol4 = [b"aabc", b"ddbc", b"efgg", b"efhh"];
    let sol5 = [b"aabc.", b"..bcd", b"eff.d", b"e.ghh", b"iigjj"];
    let sol6 = [
        b"aa.bcc", b"dd.be.", b".fg.e.", b".fg.hh", b"i.jj.k", b"i.ll.k",
    ];
    let sol7 = [
        b"aa...bc", b"....dbc", b"..eedff", b"..ghhii", b"jjg.k..", b"lm..k..", b"lmnn...",
    ];

    if n <= 2 {
        println!("-1");
        return;
    }

    if n == 3 {
        for row in sol3.iter() {
            for cell in row.iter() {
                print!("{}", *cell as char);
            }
            println!();
        }
        return;
    }

    let lu = (n / 4 - 1) as usize;

    let mut sol = vec![vec![b'.'; n as usize]; n as usize];

    for i in 0..lu {
        for y in 0..4 {
            for x in 0..4 {
                sol[y + i * 4][x + i * 4] = sol4[y][x];
            }
        }
    }

    let base = n - lu * 4;
    for y in 0..base {
        for x in 0..base {
            let c = match base {
                4 => sol4[y][x],
                5 => sol5[y][x],
                6 => sol6[y][x],
                7 => sol7[y][x],
                _ => unreachable!(),
            };
            sol[y + lu * 4][x + lu * 4] = c;
        }
    }

    for row in sol.iter() {
        for cell in row.iter() {
            print!("{}", *cell as char);
        }
        println!();
    }
}

// fn solve(x: usize, y: usize, cnt: usize, bd: &mut Vec<Vec<usize>>) {
//     let n = bd.len();

//     if y == n {
//         let mut ccx = vec![vec![false; cnt]; n];
//         let mut ccy = vec![vec![false; cnt]; n];

//         for x in 0..n {
//             for y in 0..n {
//                 ccx[x][bd[y][x]] = true;
//             }
//         }
//         for y in 0..n {
//             for x in 0..n {
//                 ccy[y][bd[y][x]] = true;
//             }
//         }

//         let cx = ccx
//             .iter()
//             .map(|cs| cs[1..].iter().filter(|b| **b).count())
//             .collect::<Vec<_>>();
//         let cy = ccy
//             .iter()
//             .map(|cs| cs[1..].iter().filter(|b| **b).count())
//             .collect::<Vec<_>>();

//         // for row in bd.iter() {
//         //     for cell in row.iter() {
//         //         print!("{}", *cell);
//         //     }
//         //     println!();
//         // }
//         // dbg!(&cx, &cy);

//         let v = cx[0];
//         if cx.into_iter().all(|w| v == w) && cy.into_iter().all(|w| v == w) {
//             println!("qual: {}", v);
//             for row in bd.iter() {
//                 print!("\"");
//                 for cell in row.iter() {
//                     print!(
//                         "{}",
//                         if *cell == 0 {
//                             '.'
//                         } else {
//                             ('a' as u8 + *cell as u8 - 1) as char
//                         }
//                     );
//                 }
//                 println!("\",");
//             }
//             println!();
//         }
//         return;
//     }

//     if x == n {
//         let mut tbl = vec![false; cnt];
//         for x in 0..n {
//             tbl[bd[y][x]] = true;
//         }

//         // Qual == 3
//         if tbl[1..].iter().filter(|b| **b).count() != 1 {
//             return;
//         }

//         solve(0, y + 1, cnt, bd);
//         return;
//     }

//     if !(x == 0 && y == 0) {
//         solve(x + 1, y, cnt, bd);
//     }

//     if x + 1 < n && bd[y][x] == 0 && bd[y][x + 1] == 0 {
//         bd[y][x] = cnt;
//         bd[y][x + 1] = cnt;
//         solve(x + 1, y, cnt + 1, bd);
//         bd[y][x] = 0;
//         bd[y][x + 1] = 0;
//     }

//     if !(x == 0 && y == 0) && y + 1 < n && bd[y][x] == 0 && bd[y + 1][x] == 0 {
//         bd[y][x] = cnt;
//         bd[y + 1][x] = cnt;
//         solve(x + 1, y, cnt + 1, bd);
//         bd[y][x] = 0;
//         bd[y + 1][x] = 0;
//     }
// }


Measured memory_bytes: 5244