#include <bits/stdc++.h>
using namespace std;
int n;
struct node {
  int index;
  long long dist;
};
bool operator<(const node& x, const node& y) { return (x.dist < y.dist); }
vector<node> pre2, post2;
vector<node> ans;
vector<node> B;
int main() {
  ios::sync_with_stdio(false);
  cin >> n;
  int ret;
  ans.push_back({1, 0});
  for (int i = 3; i <= n; ++i) {
    cout << "2 1 2 " << i << endl;
    cout.flush();
    cin >> ret;
    node x;
    x.index = i;
    cout << "1 1 2 " << i << endl;
    cout.flush();
    cin >> x.dist;
    if (ret < 0)
      pre2.push_back(x);
    else
      post2.push_back(x);
  }
  if (!pre2.empty()) {
    sort(pre2.begin(), pre2.end());
    for (int i = 0; i + 1 < (int)pre2.size(); ++i) {
      cout << "2 1 " << pre2.back().index << " " << pre2[i].index << endl;
      cout.flush();
      cin >> ret;
      if (ret < 0)
        ans.push_back(pre2[i]);
      else
        B.push_back(pre2[i]);
    }
    ans.push_back(pre2.back());
    while (!B.empty()) {
      ans.push_back(B.back());
      B.pop_back();
    }
  }
  ans.push_back({2, 0});
  if (!post2.empty()) {
    sort(post2.begin(), post2.end());
    for (int i = 0; i + 1 < (int)post2.size(); ++i) {
      cout << "2 1 " << post2.back().index << " " << post2[i].index << endl;
      cout.flush();
      cin >> ret;
      if (ret < 0)
        ans.push_back(post2[i]);
      else
        B.push_back(post2[i]);
    }
    ans.push_back(post2.back());
    while (!B.empty()) {
      ans.push_back(B.back());
      B.pop_back();
    }
  }
  cout << "0";
  for (auto& x : ans) cout << " " << x.index;
  cout << endl;
  cout.flush();
  return 0;
}
