#include <bits/stdc++.h>
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
using namespace std;
struct UnionFind {
  int num;
  vector<int> rs, ps;
  UnionFind() {}
  UnionFind(int n) : num(n), rs(n, 1), ps(n, 0) {
    iota(ps.begin(), ps.end(), 0);
  }
  int find(int x) { return (x == ps[x] ? x : ps[x] = find(ps[x])); }
  bool same(int x, int y) { return find(x) == find(y); }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rs[x] < rs[y]) swap(x, y);
    rs[x] += rs[y];
    ps[y] = x;
    num--;
  }
  int size(int x) { return rs[find(x)]; }
  int count() const { return num; }
};
using ll = long long;
ll N;
std::set<std::string> ans;
int main() {
  std::cin >> N;
  for (int i = (0); i < ((1 << (N * (N - 1) / 2))); ++i) {
    UnionFind uf(N + 10);
    ll cnt = 0;
    std::string S;
    for (int j = (0); j < (N); ++j)
      for (int k = (j + 1); k < (N); ++k) {
        if (i >> cnt & 1) uf.unite(j, k);
        ++cnt;
      }
    std::map<int, char> mp;
    char ch = 'a';
    for (int j = (0); j < (N); ++j) {
      ll root = uf.find(j);
      if (mp.count(root))
        S += mp[root];
      else {
        mp[root] = ch++;
        S += mp[root];
      }
    }
    ans.insert(S);
  }
  for (auto it = ans.begin(); it != ans.end(); ++it)
    std::cout << *it << std::endl;
  return 0;
}
