#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long x = 0, f = 1;
  char c = getchar();
  while ((c < '0' || c > '9') && (c != '-')) c = getchar();
  if (c == '-') f = -1, c = getchar();
  while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  return x * f;
}
const int N = 1010;
int n, cnt1, cnt2;
pair<long long, long long> l[N], r[N];
struct point {
  long long x, y;
  inline point operator-(const point &p) { return (point){x - p.x, y - p.y}; }
} p[N];
inline long long cross(point a, point b) { return a.x * b.y - a.y * b.x; }
inline long long query(int opt, int a, int b, int c) {
  printf("%d %d %d %d\n", opt, a, b, c), fflush(stdout);
  return read();
}
int main() {
  n = read();
  int pos = 2;
  for (register int i = (3); i <= (n); i++)
    if (query(2, 1, i, pos) > 0) pos = i;
  vector<pair<long long, long long> > v;
  for (register int i = (2); i <= (n); i++)
    if (i != pos) v.push_back(make_pair(query(1, 1, pos, i), i));
  sort((v).begin(), (v).end());
  vector<int> l, r;
  for (register int i = (0); i < (((int)(v).size()) - 1); i++)
    if (query(2, 1, v[i].second, v[i + 1].second) == 1)
      l.push_back(v[i].second);
    else
      r.push_back(v[i].second);
  l.push_back(v.back().second);
  printf("0 %d %d ", 1, pos);
  for (auto i : l) printf("%d ", i);
  reverse((r).begin(), (r).end());
  for (auto i : r) printf("%d ", i);
}
