#include <bits/stdc++.h>
using namespace std;
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
void print_time() {}
template <typename T>
void update_max(T& x, T y) {
  x = max(x, y);
}
template <typename T>
void update_min(T& x, T y) {
  x = min(x, y);
}
template <class T1, class T2>
ostream& operator<<(ostream& out, pair<T1, T2> pair) {
  return out << "(" << pair.first << ", " << pair.second << ")";
}
template <class T>
ostream& operator<<(ostream& out, vector<T> vec) {
  out << "(";
  for (auto& v : vec) out << v << ", ";
  return out << ")";
}
template <class T>
ostream& operator<<(ostream& out, set<T> vec) {
  out << "(";
  for (auto& v : vec) out << v << ", ";
  return out << ")";
}
template <class L, class R>
ostream& operator<<(ostream& out, map<L, R> vec) {
  out << "(";
  for (auto& v : vec) out << v << ", ";
  return out << ")";
}
long long ask(long long t, long long i, long long j, long long k) {
  ++i, ++j, ++k;
  cout << t << " " << i << " " << j << " " << k << endl;
  long long res;
  cin >> res;
  return res;
}
void ans(vector<long long> p) {
  cout << "0 ";
  for (long long pp : p) {
    cout << pp + 1 << " ";
  }
  cout << endl;
}
int main() {
  cout << fixed << setprecision(20);
  ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  long long n;
  cin >> n;
  vector<long long> area(n);
  vector<long long> sign(n);
  for (long long i = 2; i < n; ++i) {
    area[i] = ask(1, 0, 1, i);
    sign[i] = ask(2, 0, 1, i);
  }
  vector<long long> cnt_sign(2);
  vector<set<pair<long long, long long>>> pos(2);
  for (long long i = 2; i < n; ++i) {
    pos[(sign[i] + 1) / 2].insert({area[i], i});
    ++cnt_sign[(sign[i] + 1) / 2];
  }
  vector<vector<long long>> sorted(2);
  for (long long kek = 0; kek < 2; ++kek) {
    sorted[kek] = vector<long long>(cnt_sign[kek]);
    long long l = 0;
    long long r = cnt_sign[kek] - 1;
    while (!pos[kek].empty()) {
      pair<long long, long long> curr = *pos[kek].begin();
      pos[kek].erase(pos[kek].begin());
      long long i = 0;
      long long j = curr.second;
      if (pos[kek].empty()) {
        sorted[kek][l] = j;
        break;
      }
      long long k = pos[kek].begin()->second;
      long long q = ask(2, i, j, k);
      if (q > 0) {
        sorted[kek][l++] = j;
      } else {
        sorted[kek][r--] = j;
      }
    }
  }
  vector<long long> p;
  p.push_back(0);
  for (long long v : sorted[0]) p.push_back(v);
  p.push_back(1);
  for (long long v : sorted[1]) p.push_back(v);
  ans(p);
  print_time();
  return 0;
}
