#include <bits/stdc++.h>
using namespace std;
typedef struct Querytype {
  int a, b, c;
  bool operator==(const Querytype &other) const {
    return a == other.a && b == other.b && c == other.c;
  }
} Query;
namespace std {
template <>
struct hash<Query> {
  std::size_t operator()(const Query &k) const {
    return (k.a * 1001 + k.b) * 1001 + k.c;
  }
};
}  // namespace std
int n, nn;
vector<int> edges[2 * 1001];
unordered_map<Query, char> q;
inline bool lsize(int x) { return x <= n; }
inline bool lnode(int x) { return x > n; }
struct CENT {
  typedef bool (*SZ_COUNTER)(int);
  typedef bool (*ND_COUNTER)(int);
  int *cmax, *csize, n;
  vector<int> nodes;
  bool *rem;
  SZ_COUNTER cntr;
  ND_COUNTER nntr;
  vector<pair<int, vector<int>>> cents;
  vector<map<int, int>> cents_orig;
  CENT(int n, SZ_COUNTER cntr, ND_COUNTER nntr) : n(n), cntr(cntr), nntr(nntr) {
    cmax = (int *)malloc((this->n + 1) * sizeof(int));
    csize = (int *)malloc((this->n + 1) * sizeof(int));
    rem = (bool *)malloc((this->n + 1) * sizeof(bool));
    memset(rem, false, (this->n + 1) * sizeof(bool));
  }
  ~CENT() {
    free(cmax);
    free(csize);
    free(rem);
  }
  void dfs(int x, int p) {
    nodes.push_back(x);
    csize[x] = cntr(x) ? 1 : 0;
    cmax[x] = 0;
    for (auto i : edges[x])
      if (i != -1 && i != p && !rem[i]) {
        dfs(i, x);
        csize[x] += csize[i];
        if (csize[i] > cmax[x]) cmax[x] = csize[i];
      }
  }
  void decompose() {
    cents.clear();
    vector<int> ztl;
    map<int, int> zml;
    cents.push_back(make_pair(0, ztl));
    cents_orig.push_back(zml);
    queue<pair<int, int>> q;
    q.push(make_pair(1, 0));
    while (!q.empty()) {
      auto t = q.front();
      q.pop();
      nodes.clear();
      dfs(t.first, -1);
      int ct = -1;
      for (auto i : nodes)
        if (csize[i] * 2 >= csize[t.first] && cmax[i] * 2 <= csize[t.first] &&
            nntr(i)) {
          ct = i;
          break;
        }
      if (ct == -1) ct = t.first;
      vector<int> ctl;
      cents.push_back(make_pair(ct, ctl));
      cents_orig.push_back(zml);
      int cti = cents.size() - 1, ki = 0;
      cents[t.second].second.push_back(cti);
      for (auto i : edges[ct])
        if (i != -1 && !rem[i]) {
          q.push(make_pair(i, cti));
          cents_orig[cti][i] = ki++;
        }
      rem[ct] = true;
    }
  }
};
int get_leaf(int x) {
  if (edges[x].size() <= 1)
    return x;
  else
    return get_leaf(edges[x][1]);
}
char query(int a, int b, int c) {
  bool bab = false;
  if (a > b) {
    swap(b, a);
    bab = true;
  }
  Query qq = {.a = a, .b = b, .c = c};
  if (q.find(qq) == q.end()) {
    cout << a << " " << b << " " << c << endl;
    cin >> q[qq];
  }
  return !bab || q[qq] == 'X' ? q[qq] : (q[qq] == 'Y' ? 'Z' : 'Y');
}
inline int vfind(const vector<int> &x, int v) {
  return find(x.begin(), x.end(), v) - x.begin();
}
void run(int x) {
  CENT cent(2 * n - 1, &lsize, &lnode);
  cent.decompose();
  int i = 1;
  while (true) {
    auto ct = cent.cents[i].first;
    auto cm = cent.cents_orig[i];
    const auto &cp = cent.cents[i].second;
    char q = query(get_leaf(edges[ct][1]), get_leaf(edges[ct][2]), x);
    if (q == 'X') {
      if (cm.find(edges[ct][0]) == cm.end()) {
        if (edges[ct][0] != -1) {
          int idx = vfind(edges[edges[ct][0]], ct);
          edges[edges[ct][0]][idx] = nn;
          edges[nn].push_back(edges[ct][0]);
        } else
          edges[nn].push_back(-1);
        edges[ct][0] = nn;
        edges[x].push_back(nn);
        edges[nn].push_back(ct);
        edges[nn].push_back(x);
        nn++;
        break;
      } else
        i = cp[cm[edges[ct][0]]];
    } else {
      int k = q == 'Y' ? 2 : 1;
      if (cm.find(edges[ct][k]) == cm.end() || !lnode(edges[ct][k])) {
        int ke = edges[ct][k];
        edges[ke][0] = nn;
        edges[ct][k] = nn;
        edges[x].push_back(nn);
        edges[nn].push_back(ct);
        edges[nn].push_back(ke);
        edges[nn].push_back(x);
        nn++;
        break;
      } else
        i = cp[cm[edges[ct][k]]];
    }
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n;
  edges[1].push_back(n + 1);
  edges[2].push_back(n + 1);
  edges[n + 1].push_back(-1);
  edges[n + 1].push_back(1);
  edges[n + 1].push_back(2);
  nn = n + 2;
  for (int i = 3; i <= n; i++) run(i);
  cout << -1 << endl;
  for (int i = 1; i < 2 * n - 1; i++) cout << edges[i][0] << " ";
  cout << edges[2 * n - 1][0] << endl;
  return 0;
}
