#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, ans[N], a[N], b[N];
long long dis[N], k;
struct Node {
  int id;
  long long dis;
  bool operator<(const Node &A) const { return dis < A.dis; }
} l[N], r[N];
int lid, rid;
long long getArea(int x, int y, int z) {
  long long res;
  printf("1 %d %d %d\n", x, y, z);
  fflush(stdout);
  scanf("%lld", &res);
  return res;
}
int getDir(int x, int y, int z) {
  int res;
  printf("2 %d %d %d\n", x, y, z);
  fflush(stdout);
  scanf("%d", &res);
  return res;
}
void solve(int kind, int c[]) {
  int mark = 0;
  long long maxarea = -5e18;
  lid = rid = 0;
  for (int i = 1; i <= c[0]; i++) {
    dis[c[i]] = getArea(1, 2, c[i]);
    if (maxarea < dis[c[i]]) {
      maxarea = dis[c[i]];
      mark = c[i];
    }
  }
  for (int i = 1; i <= c[0]; i++) {
    if (c[i] == mark) continue;
    k = getDir(1, mark, c[i]);
    if (k < 0)
      l[++lid] = (Node){c[i], dis[c[i]]};
    else
      r[++rid] = (Node){c[i], dis[c[i]]};
  }
  sort(l + 1, l + lid + 1);
  sort(r + 1, r + rid + 1);
  if (kind == 0)
    ans[++ans[0]] = 1;
  else
    ans[++ans[0]] = 2;
  for (int i = 1; i <= lid; i++) ans[++ans[0]] = l[i].id;
  if (mark) ans[++ans[0]] = mark;
  for (int i = rid; i >= 1; i--) ans[++ans[0]] = r[i].id;
}
int main() {
  scanf("%d", &n);
  for (int i = 3; i <= n; i++) {
    k = getDir(1, 2, i);
    if (k < 0)
      a[++a[0]] = i;
    else
      b[++b[0]] = i;
  }
  solve(0, a);
  solve(1, b);
  printf("0 ");
  for (int i = 1; i <= ans[0]; i++) printf("%d ", ans[i]);
  putchar(10);
  return 0;
}
