#include <bits/stdc++.h>
using namespace std;
double query1(int i, int j, int k) {
  double answer;
  cout << 1 << " " << i << " " << j << " " << k << endl;
  cin >> answer;
  return answer;
}
int query2(int i, int j, int k) {
  int answer;
  cout << 2 << " " << i << " " << j << " " << k << endl;
  cin >> answer;
  return answer;
}
struct node {
  int loc;
  double dis;
} now;
vector<node> loc_left, loc_right;
vector<int> ans;
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin >> n;
  for (int i = 3; i <= n; i++) {
    if (query2(1, 2, i) == 1) {
      now.loc = i;
      loc_left.push_back(now);
    } else {
      now.loc = i;
      loc_right.push_back(now);
    }
  }
  for (int i = 0; i < loc_left.size(); i++) {
    loc_left[i].dis = query1(1, 2, loc_left[i].loc);
  }
  for (int i = 0; i < loc_right.size(); i++) {
    loc_right[i].dis = query1(1, 2, loc_right[i].loc);
  }
  sort(loc_left.begin(), loc_left.end(),
       [](const node &a, const node &b) { return a.dis > b.dis; });
  sort(loc_right.begin(), loc_right.end(),
       [](const node &a, const node &b) { return a.dis > b.dis; });
  ans.push_back(0);
  ans.push_back(1);
  vector<int> loc_right_l, loc_right_r;
  if (!loc_right.empty()) {
    int right_max = loc_right[0].loc;
    for (int i = 0; i < loc_right.size(); i++) {
      if (right_max == loc_right[i].loc) continue;
      if (query2(1, right_max, loc_right[i].loc) == 1) {
        loc_right_l.push_back(loc_right[i].loc);
      } else {
        loc_right_r.push_back(loc_right[i].loc);
      }
    }
    if (!loc_right_r.empty()) {
      for (int i = loc_right_r.size() - 1; i >= 0; i--) {
        ans.push_back(loc_right_r[i]);
      }
    }
    ans.push_back(right_max);
    for (int i = 0; i < loc_right_l.size(); i++) {
      ans.push_back(loc_right_l[i]);
    }
  }
  ans.push_back(2);
  vector<int> loc_left_l, loc_left_r;
  if (!loc_left.empty()) {
    int left_max = loc_left[0].loc;
    for (int i = 0; i < loc_left.size(); i++) {
      if (left_max == loc_left[i].loc) continue;
      if (query2(1, left_max, loc_left[i].loc) == 1) {
        loc_left_l.push_back(loc_left[i].loc);
      } else {
        loc_left_r.push_back(loc_left[i].loc);
      }
    }
    if (!loc_left_r.empty()) {
      for (int i = loc_left_r.size() - 1; i >= 0; i--) {
        ans.push_back(loc_left_r[i]);
      }
    }
    ans.push_back(left_max);
    for (int i = 0; i < loc_left_l.size(); i++) {
      ans.push_back(loc_left_l[i]);
    }
  }
  for (int i = 0; i < ans.size(); i++) {
    cout << ans[i] << " ";
  }
  cout << endl;
  return 0;
}
