#include <bits/stdc++.h>
using namespace std;
template <typename T>
struct outputer;
struct outputable {};
template <typename T>
inline auto sqr(T x) -> decltype(x * x) {
  return x * x;
}
template <typename T1, typename T2>
inline bool umx(T1& a, T2 b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T1, typename T2>
inline bool umn(T1& a, T2 b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
const int N = 1000;
int64_t y[N];
int main() {
  int n;
  cin >> n;
  for (int i = int(0); i < int(n); ++i) {
    if (i < 2) {
      y[i] = 0;
    } else {
      int64_t a1, a2;
      cout << 1 << ' ' << 1 << ' ' << 2 << ' ' << i + 1 << endl;
      cin >> a1;
      cout << 2 << ' ' << 1 << ' ' << 2 << ' ' << i + 1 << endl;
      cin >> a2;
      y[i] = a1 * a2;
    }
  };
  int mni = 0, mxi = 0;
  int64_t mn = y[0], mx = y[0];
  for (int i = int(0); i < int(n); ++i) {
    if (umn(mn, y[i])) {
      mni = i;
    }
    if (umx(mx, y[i])) {
      mxi = i;
    }
  }
  vector<int> v1, v2;
  for (int i = int(0); i < int(n); ++i) {
    if (i == mni || i == mxi) {
      continue;
    }
    int64_t val;
    cout << 2 << ' ' << mni + 1 << ' ' << mxi + 1 << ' ' << i + 1 << endl;
    cin >> val;
    if (val == -1) {
      v1.emplace_back(i);
    } else {
      v2.emplace_back(i);
    }
  }
  sort((v1).begin(), (v1).end(), [&](int i, int j) { return y[i] < y[j]; });
  sort((v2).begin(), (v2).end(), [&](int i, int j) { return y[i] < y[j]; });
  vector<int> v;
  v.emplace_back(mni);
  for (int i = int(0); i < int(((int)(v1).size())); ++i) {
    v.emplace_back(v1[i]);
  }
  v.emplace_back(mxi);
  for (int i = int(((int)(v2).size())) - 1; i >= int(0); --i) {
    v.emplace_back(v2[i]);
  }
  int pos = 0;
  for (int i = int(0); i < int(((int)(v).size())); ++i) {
    if (v[i] == 0) {
      pos = i;
    }
  }
  rotate(v.begin(), v.begin() + pos, v.end());
  cout << 0;
  for (int i = int(0); i < int(((int)(v).size())); ++i) {
    cout << ' ' << v[i] + 1;
  }
  cout << endl;
  return 0;
}
