use std::vec::Vec;
use std::cmp::max;

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace().map(|e| e.parse().ok().unwrap()).collect()
}

fn read_touple<T: std::str::FromStr + Copy>() -> (T, T) {
  let v: Vec<T> = read_vec();
  assert_eq!(v.len(), 2);
  (v[0], v[1])
}

fn main() {
    let N: usize = read();
    let alpha = vec!['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' , 'j'];
    let mut tot = Vec::new();
    dfs(N, 1, vec![], &mut tot);
    let mut tot1 = vec![];

    for i in 0..tot.len() {
      if check(&tot[i]) {
        tot1.push(tot[i].clone());
      }
    }
   
    tot1.sort();

    for v in tot1 {
      let ans: String = v.into_iter().collect();
      println!("{}", ans);
    }
}


fn dfs(N: usize, n: usize, v: Vec<char>, tot: &mut Vec<Vec<char>>) {
    let alpha = vec!['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' , 'j'];
    if n == N+1 {
      tot.push(v.clone());
      return
    }

    for i in 0..n {
      let mut x = v.clone();
      x.push(alpha[i]);
      dfs(N, n+1, x, tot);
    }
}

fn check(s: &Vec<char>) -> bool {
     let alpha = vec!['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' , 'j'];
     let mut res = vec![0; 10];
     let n = s.len();
     for &c in s {
        for i in 0..10 {
          if c == alpha[i] {
            res[i] += 1;
          }
        }
     }

     let mut count = 0;
     let mut idx = 0;
     for i in 0..10 {
       if res[i] > 0 {
        count += 1;
       }
       if res[i] > 0 {
          idx = max(idx, i);
       }
     }

     idx < count
}