//我为什么静不下心来看Anime和Light Novel啊
//淦，只能被迫学习，自闭了
#include<bits/stdc++.h>
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define FOR(i,x,y) for (register int i=(x);i<(y);i++)
#define Dow(i,x,y) for (register int i=(x);i>=(y);i--)
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define siz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define fil(a,b) memset((a),(b),sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pa;
typedef pair<ll,ll> PA;
inline ll read(){
    ll 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;
PA l[N],r[N];
struct point{
	ll x,y;
	inline point operator - (const point &p){return (point){x-p.x,y-p.y};}
}p[N];
inline ll cross(point a,point b){return a.x*b.y-a.y*b.x;}

inline ll query(int opt,int a,int b,int c){
	printf("%d %d %d %d\n",opt,a,b,c),fflush(stdout);
	return read();
/*	if (opt==1){
		point A=p[b]-p[a],B=p[c]-p[a];
		return abs(cross(A,B));
	} else {
		point A=p[b]-p[a],B=p[c]-p[a];
		return cross(A,B)>0?1:-1;
	}*/
}

int main(){
	n=read();
//	For(i,1,n) p[i]=(point){read(),read()};
	For(i,3,n){
		if (query(2,1,2,i)<0){
			int pos1=0,pos2=cnt2+1;
			ll s=query(1,1,2,i);
			if (!cnt2){r[++cnt2]=mp(s,i);continue;}
			For(j,1,cnt2){
				if (s>=r[j].fi) pos1=j;
				if (r[j].fi>=r[j+1].fi) break;
			}
			Dow(j,cnt2,1){
				if (s>=r[j].fi) pos2=j;
				if (r[j].fi>=r[j-1].fi) break;
			}
			if (r[pos1].fi==s||cnt2==pos1){
				if (query(2,1,r[pos1].se,i)>0) ++pos1;
				++cnt2;
				Dow(j,cnt2,pos1+1) r[j]=r[j-1];
				r[pos1]=mp(s,i);
			} else {
				++pos1,++cnt2;
				if (query(2,1,r[pos1].se,i)<0){
					Dow(j,cnt2,pos1+1) r[j]=r[j-1];
					r[pos1]=mp(s,i);
				} else {
					Dow(j,cnt2,pos2+1) r[j]=r[j-1];
					r[pos2]=mp(s,i);
				}
			}
		} else {
			int pos1=0,pos2=cnt1+1;
			ll s=query(1,1,2,i);
			if (!cnt1){l[++cnt1]=mp(s,i);continue;}
			For(j,1,cnt1){
				if (s>=l[j].fi) pos1=j;
				if (l[j].fi>=l[j+1].fi) break;
			}
			Dow(j,cnt1,1){
				if (s>=l[j].fi) pos2=j;
				if (l[j].fi>=l[j-1].fi) break;
			}
			if (l[pos1].fi==s||cnt1==pos1){
				if (query(2,1,l[pos1].se,i)<0) ++pos1;
				++cnt1;
				Dow(j,cnt1,pos1+1) l[j]=l[j-1];
				l[pos1]=mp(s,i);
			} else {
				++pos1,++cnt1,l[cnt1]=l[cnt1-1];
				if (query(2,1,l[pos1].se,i)>0){
					Dow(j,cnt1,pos1+1) l[j]=l[j-1];
					l[pos1]=mp(s,i);
				} else {
					Dow(j,cnt1,pos2+1) l[j]=l[j-1];
					l[pos2]=mp(s,i);
				}
			}
		}
	}
	printf("0 1 ");
	For(i,1,cnt2) printf("%d ",r[i].se);
	printf("2 "),reverse(l+1,l+1+cnt1);
	For(i,1,cnt1) printf("%d ",l[i].se);
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
#define int         int64_t
#define ii          pair<int,int>
#define dd          pair<double,double>
#define vi          vector<int>
#define pb          push_back
#define all(x)      (x).begin(), (x).end()
#define checkBit(v, p)      (v&(1LL << p))
#define loop(i,a,b) for(int i = a;i < int(b);i++)
#define x           first
#define y           second
#define chkmin(a,b) (a) = min((a), (b))
#define chkmax(a,b) (a) = max((a), (b))
using namespace std;
int inf = 1e9, mod = 1e9;

inline int ask(int base, int p1, int p2){
    cout << base + 1<<' '<<p1 + 1<<' '<<p2 + 1<<endl;
    fflush(stdout);
    int ans; cin >> ans;
    return ans;
}

int ask1(int base, int p1, int p2){
    cout << 1<<' ';
    return ask(base, p1,p2);
}

int ask2(int base, int p1, int p2){
    cout << 2<<' ';
    return ask(base, p1,p2);
}

int32_t main()
{
    ios_base::sync_with_stdio(false); cout << fixed <<setprecision(0);
    int n; cin >> n;
    int mini = 1;
    for(int i = 2;i<n;i++) if(ask2(0, mini, i) < 0) mini = i;
    vi arr(n, 0);
    ii maxi(-1,-1);
    for(int i=1;i<n;i++){
        if(i == mini) continue;
        arr[i] = ask1(0, mini, i);
        chkmax(maxi, ii(arr[i], i));
    }
    vector<ii> be, af;
    for(int i=1;i<n;i++){
        if(i == mini || i == maxi.y) continue;
        if(ask2(0, maxi.y, i) > 0) af.pb({arr[i], i});
        else be.pb({arr[i], i});
    }
    sort(all(be));
    sort(all(af), greater<ii>());
    cout <<0<<' ';
    cout << 1<<' '<< mini + 1<<' ';
    for(auto &v:be) cout <<v.y + 1<<' ';
    cout << maxi.y + 1<<' ';
    for(auto &v:af) cout <<v.y + 1<<' ';
    cout << endl;
    return 0;
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
#define int         int64_t
#define ii          pair<int,int>
#define dd          pair<double,double>
#define vi          vector<int>
#define pb          push_back
#define all(x)      (x).begin(), (x).end()
#define checkBit(v, p)      (v&(1LL << p))
#define loop(i,a,b) for(int i = a;i < int(b);i++)
#define x           first
#define y           second
#define chkmin(a,b) (a) = min((a), (b))
#define chkmax(a,b) (a) = max((a), (b))
using namespace std;
int inf = 1e9, mod = 1e9;

inline int ask(int base, int p1, int p2){
    cout << base + 1<<' '<<p1 + 1<<' '<<p2 + 1<<endl;
    fflush(stdout);
    int ans; cin >> ans;
    return ans;
}

int ask1(int base, int p1, int p2){
    cout << 1<<' ';
    return ask(base, p1,p2);
}

int ask2(int base, int p1, int p2){
    cout << 2<<' ';
    return ask(base, p1,p2);
}

int32_t main()
{
    ios_base::sync_with_stdio(false); cout << fixed <<setprecision(0);
    int n; cin >> n;
    int mini = 1;
    for(int i = 2;i<n;i++) if(ask2(0, mini, i) < 0) mini = i;
    vi arr(n, 0);
    ii maxi(-1,-1);
    for(int i=1;i<n;i++){
        if(i == mini) continue;
        arr[i] = ask1(0, mini, i);
        chkmax(maxi, ii(arr[i], i));
    }
    vector<ii> be, af;
    for(int i=1;i<n;i++){
        if(i == mini || i == maxi.y) continue;
        if(ask2(0, maxi.y, i) > 0) af.pb({arr[i], i});
        else be.pb({arr[i], i});
    }
    sort(all(be));
    sort(all(af), greater<ii>());
    cout << 1<<' '<< mini + 1<<' ';
    for(auto &v:be) cout <<v.y + 1<<' ';
    cout << maxi.y + 1<<' ';
    for(auto &v:af) cout <<v.y + 1<<' ';
    cout << endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 1003;

ll qry(int ty, int x, int y, int z)
{
    printf("%d %d %d %d\n", ty, x, y, z);
    fflush(stdout);
    ll ans;
    scanf("%lld", &ans);
    return ans;
}

int n;
ll s[N];

bool so(int x, int y)
{
    return s[x] < s[y];
}

void solv()
{
    scanf("%d", &n);
    vector<int> l, r, ans;
    for (int i = 3; i <= n; ++i)
    {
        if (qry(2, 1, 2, i) < 0)
            r.push_back(i);
        else
            l.push_back(i);
    }
    for (int i = 3; i <= n; ++i)
        s[i] = qry(1, 1, 2, i);
    sort(r.begin(), r.end(), so);
    vector<int> r0, r1;
    for (int i = 0; i < sz(r) - 1; ++i)
    {
        if (qry(2, 1, r.back(), r[i]) < 0)
            r0.push_back(r[i]);
        else
            r1.push_back(r[i]);
    }
    if (!r.empty())
        r0.push_back(r.back());
    sort(l.begin(), l.end(), so);
    vector<int> l0, l1;
    for (int i = 0; i < sz(l) - 1; ++i)
    {
        if (qry(2, 2, l.back(), l[i]) < 0)
            l0.push_back(l[i]);
        else
            l1.push_back(l[i]);
    }
    if (!l.empty())
        l0.push_back(l.back());
    ans.push_back(1);
    for (int i = 0; i < r0.size(); ++i)
        ans.push_back(r0[i]);
    reverse(r1.begin(), r1.end());
    for (int i = 0; i < r1.size(); ++i)
        ans.push_back(r1[i]);
    ans.push_back(2);
    for (int i = 0; i < l0.size(); ++i)
        ans.push_back(l0[i]);
    reverse(l1.begin(), l1.end());
    for (int i = 0; i < l1.size(); ++i)
        ans.push_back(l1[i]);
    printf("0 ");
    for (int i = 0; i < n; ++i)
        printf("%d ", ans[i]);
    printf("\n");
    fflush(stdout);
}

int main()
{
    #ifdef SOMETHING
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    #endif // SOMETHING
    solv();
    return 0;
}

//while ((double)clock() / CLOCKS_PER_SEC <= 0.9){}


#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 1003;

ll qry(int ty, int x, int y, int z)
{
    printf("%d %d %d %d\n", ty, x, y, z);
    fflush(stdout);
    ll ans;
    scanf("%lld", &ans);
    return ans;
}

int n;
ll s[N];

bool so(int x, int y)
{
    return s[x] < s[y];
}

void solv()
{
    scanf("%d", &n);
    vector<int> l, r, ans;
    for (int i = 3; i <= n; ++i)
    {
        if (qry(2, 1, 2, i) < 0)
            r.push_back(i);
        else
            l.push_back(i);
    }
    for (int i = 3; i <= n; ++i)
        s[i] = qry(1, 1, 2, i);
    sort(r.begin(), r.end(), so);
    vector<int> r0, r1;
    for (int i = 0; i < sz(r) - 1; ++i)
    {
        if (qry(2, 1, r.back(), r[i]) < 0)
            r0.push_back(r[i]);
        else
            r1.push_back(r[i]);
    }
    r0.push_back(r.back());
    sort(l.begin(), l.end(), so);
    vector<int> l0, l1;
    for (int i = 0; i < sz(l) - 1; ++i)
    {
        if (qry(2, 2, l.back(), l[i]) < 0)
            l0.push_back(l[i]);
        else
            l1.push_back(l[i]);
    }
    l0.push_back(l.back());
    ans.push_back(1);
    for (int i = 0; i < r0.size(); ++i)
        ans.push_back(r0[i]);
    reverse(r1.begin(), r1.end());
    for (int i = 0; i < r1.size(); ++i)
        ans.push_back(r1[i]);
    ans.push_back(2);
    for (int i = 0; i < l0.size(); ++i)
        ans.push_back(l0[i]);
    reverse(l1.begin(), l1.end());
    for (int i = 0; i < l1.size(); ++i)
        ans.push_back(l1[i]);
    printf("0 ");
    for (int i = 0; i < n; ++i)
        printf("%d ", ans[i]);
    printf("\n");
    fflush(stdout);
}

int main()
{
    #ifdef SOMETHING
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    #endif // SOMETHING
    solv();
    return 0;
}

//while ((double)clock() / CLOCKS_PER_SEC <= 0.9){}


#include <bits/stdc++.h>

using namespace std;
priority_queue<pair<double,int>> q_m;
priority_queue<pair<double,int>> q_p;

struct q{
    int num;
    q* left;
    q* right;
};
q* prev_a;
void push_left(q* point,int a)
{
    q* t = new q;
    t->num = a;
    t->right = point;
    t->left = point->left;
    point->left->right = t;
    point->left = t;
    prev_a = t;
}
void push_right(q* point,int a)
{
    q* t = new q;
    t->num = a;
    t->left = point;
    t->right = point->right;
    point ->right ->left = t;
    point->right = t;
    prev_a = t;
}
int main()
{
    int n;
    cin >> n;
    int t0;
    double sq;
    for(int i = 3;i <=n; i++)
    {
        cout <<"2 1 2 " << i << '\n';
        cout.flush();
        cin >> t0;
        cout <<"1 1 2 " << i << '\n';
        cout.flush();
        cin >> sq;
        if(t0 == 1)
        {
            q_p.push({-sq,i});

        }
        else
        {
            q_m.push({-sq,i});
        }
    }
    q* h, *t;
    h = new q;
    h->num = 1;
    t = new q;
    t->num = 2;
    h->left=h->right=t;
    t->left=t->right=h;
    pair<double,int> p;
    if(q_m.size()>0)
    {
        p = q_m.top();
        q_m.pop();
        push_right(h,p.second);
        while(q_m.size()>0)
        {
            p = q_m.top();
            q_m.pop();
            cout << "2 1 " << prev_a->num << " " << p.second << '\n';
            cout.flush();
            cin >> t0;
            if(t0 == 1)
            {
                push_right(prev_a,p.second);
            }
            else
            {
                push_left(prev_a,p.second);
            }
        }
    }
    if(q_p.size()>0)
    {
        p = q_p.top();
        q_p.pop();
        push_left(h,p.second);
        while(q_p.size()>0)
        {
            p = q_p.top();
            q_p.pop();
            cout << "2 1 " << prev_a->num << " " << p.second << '\n';
            cout.flush();
            cin >> t0;
            if(t0 == 1)
            {
                push_right(prev_a,p.second);
            }
            else
            {
                push_left(prev_a,p.second);
            }
        }
    }
    cout << "0 ";
    q* t1 = h;
    do
    {
        cout <<t1->num << ' ';
        t1 = t1 ->right;
    }
    while(t1->num != 1);
    cout << '\n';
}


#include <bits/stdc++.h>

using namespace std;
priority_queue<pair<double,int>> q_m;
priority_queue<pair<double,int>> q_p;

struct q{
    int num;
    q* left;
    q* right;
};
q* prev_a;
void push_left(q* point,int a)
{
    q* t = new q;
    t->num = a;
    t->right = point;
    t->left = point->left;
    point->left->right = t;
    point->left = t;
    prev_a = t;
}
void push_right(q* point,int a)
{
    q* t = new q;
    t->num = a;
    t->left = point;
    t->right = point->right;
    point ->right ->left = t;
    point->right = t;
    prev_a = t;
}
int main()
{
    int n;
    cin >> n;
    int t0;
    double sq;
    for(int i = 3;i <=n; i++)
    {
        cout <<"2 1 2 " << i << '\n';
        cout.flush();
        cin >> t0;
        cout <<"1 1 2 " << i << '\n';
        cout.flush();
        cin >> sq;
        if(t0 == 1)
        {
            q_p.push({-sq,i});

        }
        else
        {
            q_m.push({-sq,i});
        }
    }
    q* h, *t;
    h = new q;
    h->num = 2;
    t = new q;
    t->num = 1;
    h->left=h->right=t;
    t->left=t->right=h;
    pair<double,int> p;
    if(q_m.size()>0)
    {
        p = q_m.top();
        q_m.pop();
        push_right(h,p.second);
        while(q_m.size()>0)
        {
            p = q_m.top();
            q_m.pop();
            cout << "2 1 " << prev_a->num << " " << p.second << '\n';
            cout.flush();
            cin >> t0;
            if(t0 == 1)
            {
                push_right(prev_a,p.second);
            }
            else
            {
                push_left(prev_a,p.second);
            }
        }
    }
    if(q_p.size()>0)
    {
        p = q_p.top();
        q_p.pop();
        push_left(h,p.second);
        while(q_p.size()>0)
        {
            p = q_p.top();
            q_p.pop();
            cout << "2 1 " << prev_a->num << " " << p.second << '\n';
            cout.flush();
            cin >> t0;
            if(t0 == 1)
            {
                push_left(prev_a,p.second);
            }
            else
            {
                push_right(prev_a,p.second);
            }
        }
    }
    cout << "0 ";
    q* t1 = t;
    do
    {
        cout <<t1->num << ' ';
        t1 = t1 ->left;
    }
    while(t1->num != 1);
    cout << '\n';
}


#include <bits/stdc++.h>

using namespace std;
priority_queue<pair<long long,int>> q_m;
priority_queue<pair<long long,int>> q_p;

struct q{
    int num;
    q* left;
    q* right;
};
q* prev_a;
void push_left(q* point,int a)
{
    q* t = new q;
    t->num = a;
    t->right = point;
    t->left = point->left;
    point->left->right = t;
    point->left = t;
    prev_a = t;
}
void push_right(q* point,int a)
{
    q* t = new q;
    t->num = a;
    t->left = point;
    t->right = point->right;
    point ->right ->left = t;
    point->right = t;
    prev_a = t;
}
int main()
{
    int n;
    cin >> n;
    int t0;
    long long sq;
    for(int i = 3;i <=n; i++)
    {
        cout <<"2 1 2 " << i << '\n';
        cout.flush();
        cin >> t0;
        cout <<"1 1 2 " << i << '\n';
        cout.flush();
        cin >> sq;
        if(t0 == 1)
        {
            q_p.push({-sq,i});

        }
        else
        {
            q_m.push({-sq,i});
        }
    }
    q* h, *t;
    h = new q;
    h->num = 2;
    t = new q;
    t->num = 1;
    h->left=h->right=t;
    t->left=t->right=h;
    pair<long long,int> p;
    if(q_m.size()>0)
    {
        p = q_m.top();
        q_m.pop();
        push_right(h,p.second);
        while(q_m.size()>0)
        {
            p = q_m.top();
            q_m.pop();
            cout << "2 1 " << prev_a->num << " " << p.second << '\n';
            cout.flush();
            cin >> t0;
            if(t0 == 1)
            {
                push_right(prev_a,p.second);
            }
            else
            {
                push_left(prev_a,p.second);
            }
        }
    }
    if(q_p.size()>0)
    {
        p = q_p.top();
        q_p.pop();
        push_left(h,p.second);
        while(q_p.size()>0)
        {
            p = q_p.top();
            q_p.pop();
            cout << "2 1 " << prev_a->num << " " << p.second << '\n';
            cout.flush();
            cin >> t0;
            if(t0 == 1)
            {
                push_left(prev_a,p.second);
            }
            else
            {
                push_right(prev_a,p.second);
            }
        }
    }
    cout << "0 ";
    q* t1 = t;
    do
    {
        cout <<t1->num << ' ';
        t1 = t1 ->right;
    }
    while(t1->num != 1);
    cout << '\n';
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll q1(int i, int j, int k){
    printf("1 %d %d %d\n",i,j,k);
    fflush(stdout);
    ll ans;
    scanf("%lld",&ans);
    return ans;
}

int q2(int i, int j, int k){
    printf("2 %d %d %d",i,j,k);
    fflush(stdout);
    int ans;
    scanf("%d",&ans);
    return (ans+1)/2;
}

vector<pair<ll,int>> pvec[2];
vector<pair<ll,int>> ptmp[2];
vector<int> ans;

void solve(int f, int d){
    int psz = (int)pvec[f].size();
    if(!psz)
        return;
    ptmp[0].clear();
    ptmp[1].clear();
    sort(pvec[f].begin(),pvec[f].end());
    int m = pvec[f][psz-1].second;
    for(int i = 0; i<psz-1; i++){
        int a2 = q2(m,pvec[f][i].second,d);
        ptmp[a2].push_back(pvec[f][i]);
    }
    for(auto it:ptmp[0])
        ans.push_back(it.second);
    ans.push_back(m);
    reverse(ptmp[1].begin(),ptmp[1].end());
    for(auto it:ptmp[1])
        ans.push_back(it.second);
}

int main(){
    int n;
    scanf("%d",&n);
    for(int i = 3; i<=n; i++){
        ll a1 = q1(1,i,2);
        int a2 = q2(1,i,2);
        pvec[a2].push_back({a1,i});
    }
    ans.push_back(1);
    solve(1,2);
    ans.push_back(2);
    solve(0,1);
    for(auto it:ans)
        printf("%d ",it);
    printf("\n");
    fflush(stdout);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll q1(int i, int j, int k){
    printf("1 %d %d %d\n",i,j,k);
    fflush(stdout);
    ll ans;
    scanf("%lld",&ans);
    return ans;
}

int q2(int i, int j, int k){
    printf("2 %d %d %d\n",i,j,k);
    fflush(stdout);
    int ans;
    scanf("%d",&ans);
    return (ans+1)/2;
}

vector<pair<ll,int>> pvec[2];
vector<pair<ll,int>> ptmp[2];
vector<int> ans;

void solve(int f, int d){
    int psz = (int)pvec[f].size();
    if(!psz)
        return;
    ptmp[0].clear();
    ptmp[1].clear();
    sort(pvec[f].begin(),pvec[f].end());
    int m = pvec[f][psz-1].second;
    for(int i = 0; i<psz-1; i++){
        int a2 = q2(m,pvec[f][i].second,d);
        ptmp[a2].push_back(pvec[f][i]);
    }
    for(auto it:ptmp[0])
        ans.push_back(it.second);
    ans.push_back(m);
    reverse(ptmp[1].begin(),ptmp[1].end());
    for(auto it:ptmp[1])
        ans.push_back(it.second);
}

int main(){
    int n;
    scanf("%d",&n);
    for(int i = 3; i<=n; i++){
        ll a1 = q1(1,i,2);
        int a2 = q2(1,i,2);
        pvec[a2].push_back({a1,i});
    }
    ans.push_back(1);
    solve(1,2);
    ans.push_back(2);
    solve(0,1);
    printf("0 ");
    for(auto it:ans)
        printf("%d ",it);
    printf("\n");
    fflush(stdout);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll q1(int i, int j, int k){
    printf("1 %d %d %d\n",i,j,k);
    fflush(stdout);
    ll ans;
    scanf("%lld",&ans);
    return ans;
}

int q2(int i, int j, int k){
    printf("2 %d %d %d",i,j,k);
    fflush(stdout);
    int ans;
    scanf("%d",&ans);
    return (ans+1)/2;
}

vector<pair<ll,int>> pvec[2];
vector<pair<ll,int>> ptmp[2];
vector<int> ans;

void solve(int f, int d){
    int psz = (int)pvec[f].size();
    if(!psz)
        return;
    ptmp[0].clear();
    ptmp[1].clear();
    sort(pvec[f].begin(),pvec[f].end());
    int m = pvec[f][psz-1].second;
    for(int i = 0; i<psz-1; i++){
        int a2 = q2(m,pvec[f][i].second,d);
        ptmp[a2].push_back(pvec[f][i]);
    }
    for(auto it:ptmp[0])
        ans.push_back(it.second);
    ans.push_back(m);
    reverse(ptmp[1].begin(),ptmp[1].end());
    for(auto it:ptmp[1])
        ans.push_back(it.second);
}

int main(){
    int n;
    scanf("%d",&n);
    for(int i = 3; i<=n; i++){
        ll a1 = q1(1,i,2);
        int a2 = q2(1,i,2);
        pvec[a2].push_back({a1,i});
    }
    ans.push_back(1);
    solve(1,2);
    ans.push_back(2);
    solve(0,1);
    printf("0 ");
    for(auto it:ans)
        printf("%d ",it);
    printf("\n");
    fflush(stdout);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll q1(int i, int j, int k){
    printf("1 %d %d %d\n",i,j,k);
    fflush(stdout);
    ll ans;
    scanf("%lld",&ans);
    return ans;
}

int q2(int i, int j, int k){
    printf("2 %d %d %d",i,j,k);
    fflush(stdout);
    int ans;
    scanf("%d",&ans);
    return (ans+1)/2;
}

vector<pair<ll,int>> pvec[2];
vector<pair<ll,int>> ptmp[2];
vector<int> ans;

void solve(int f, int d){
    int psz = (int)pvec[f].size();
    if(!psz)
        return;
    ptmp[0].clear();
    ptmp[1].clear();
    sort(pvec[f].begin(),pvec[f].end());
    int m = pvec[f][psz-1].second;
    for(int i = 0; i<psz-1; i++){
        int a2 = q2(m,pvec[f][i].second,d);
        ptmp[a2].push_back(pvec[f][i]);
    }
    for(auto it:ptmp[0])
        ans.push_back(it.second);
    ans.push_back(m);
    reverse(ptmp[1].begin(),ptmp[1].end());
    for(auto it:ptmp[1])
        ans.push_back(it.second);
}

int main(){
    int n;
    scanf("%d",&n);
    for(int i = 3; i<=n; i++){
        ll a1 = q1(1,i,2);
        int a2 = q2(1,i,2);
        pvec[a2].push_back({a1,i});
    }
    ans.push_back(1);
    solve(1,2);
    ans.push_back(2);
    solve(0,1);
    for(auto it:ans)
        printf("%d ",it);
    printf("\n");
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

int n;

void check_if_zero(long long x){
    if (x == 0) exit(0);
}

long long get_area(int a,int b,int c){
    long long result;
    cout << 1 << ' ' << a << ' ' << b << ' ' << c << endl;
    cin >> result;
    check_if_zero(result);
    assert(result > 0);
    return result;
}

int get_sign(int o,int a,int b){
    int result;
    cout << 2 << ' ' << o << ' ' << a << ' ' << b << endl;
    cin >> result;
    check_if_zero(result);
    assert(abs(result) == 1);
    return result;
}

vector <int> lef, rig;

void divide(){
    for(int i=3;i<=n;i++){
        int sign = get_sign(1, 2, i);

        if (sign == 1)
            lef.push_back(i);
        else
            rig.push_back(i);
    }
}

long long area12[1005];

void _do(vector<int> &lst){
    if (lst.size() <= 1)
        return;

    long long best = 0;
    for(auto v: lst){
        area12[v] = get_area(1, 2, v);
        if (area12[v] > area12[best])
            best = v;
    }

    vector <int> l, r;
    for(auto v: lst){
        if (v == best)
            continue;

        if (get_sign(1, best, v) == 1)
            l.push_back(v);
        else
            r.push_back(v);
    }

    sort(l.begin(), l.end(), [&](int x,int y){
        return area12[x] > area12[y];
    });
    sort(r.begin(), r.end(), [&](int x,int y){
        return area12[x] < area12[y];
    });

    lst.clear();
    for(auto v: r)  lst.push_back(v);
    lst.push_back(best);
    for(auto v: l)  lst.push_back(v);
}

void answer(){
    cout << 0 << ' ' << 1 << ' ';
    for(auto v: rig)  cout << v << ' ';
    cout << 2 << ' ';
    for(auto v: lef)  cout << v << ' ';
    cout << endl;
}

int main(){
    cin >> n;
    assert(n >= 3);

    divide();   // n-2 queries
    _do(lef);
    _do(rig);   //  2*(n-2) - 1 or 2*(n-2) - 2 queries
    answer();
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fi first
#define se second
#define for0(i, a, b) for(ll i = a; i < b; ++i)
#define for1(i, a, b) for(ll i = a; i <= b; ++i)
#define forw0(i, a, b) for(ll i = a - 1; i >= b; --i)
#define forw1(i, a, b) for(ll i = a; i >= b; --i)
#define fora(v, a) for(auto v : a)
#define bp __builtin_popcount
#define bpll __builtin_popcountll

typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<ll> vll;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;

const int mod1 = 1e9 + 7, mod2 = 998244353, maxn = 1e7 + 10, K = 26, maxlog = 19;
const ll infll = 1e18;
const double pi = acos(-1);

/*
1. 1-2 is pivot edge
2. queries -> left or right of pivot edge
3. for each half, find the vertex has the furthest distance to 1-2
4. sort remain points
*/

ll n, piv1, piv2;
vpll le, ri;
vll lel, ler, ril, rir, l, r;

bool cmp(pll a, pll b){
	return a.fi > b.fi;
}
void solve(){
	cin >> n;
	for1(i, 3, n){
		cout << 2 << ' ' << 1 << ' ' << 2 << ' ' << i << endl;
		int resp; cin >> resp;
		//cross product > 0 means i is to the left of 1-> 2, right otherwise
		if(resp == 1) le.pb(mp(-1, i));
		else ri.pb(mp(-1, i));
	}
	if(le.size() > 1){
		fora(v, le){
			cout << 1 << ' ' << 1 << ' ' << 2 << ' ' << v.se << endl;
			ll resp; cin >> resp; v.fi = resp;
		}
		sort(le.begin(), le.end());
		piv1 = le.back().se; le.pop_back();
		fora(v, le){
			cout << 2 << ' ' << 1 << ' ' << piv1 <<  ' ' << v.se << endl;
			ll resp; cin >> resp;
			if(resp == 1){
				lel.pb(v.se);
			}
			else ler.pb(v.se);
		}
		fora(v, ler) l.pb(v);
		l.pb(piv1);
		if(lel.size() > 0){
			forw0(i, (ll)lel.size(), 0){
				l.pb(lel[i]);
			}
		}
	}
	else if(le.size() == 1){
		l.pb(le[0].se);
	}
	if(ri.size() > 1){
		fora(v, ri){
			cout << 1 << ' ' << 1 << ' ' << 2 << ' ' << v.se << endl;
			ll resp; cin >> resp; v.fi = resp;
		}
		sort(ri.begin(), ri.end());
		piv2 = ri.back().se; ri.pop_back();
		fora(v, ri){
			cout << 2 << ' ' << 1 << ' ' << piv2 << ' ' << v.se << endl;
			ll resp; cin >> resp;
			if(resp == 1){
				ril.pb(v.se);
			}
			else rir.pb(v.se);
		}
		fora(v, rir) r.pb(v);
		r.pb(piv2);
		if(ril.size() > 0){
			forw0(i, (ll)ril.size(), 0){
				r.pb(ril[i]);
			}
		}
	}
	else if(ri.size() == 1){
		r.pb(ri[0].se);
	}
	cout << 0 << ' ' << 1 << ' ';
	fora(v, r) cout << v << ' ';
	cout << 2 << ' ';
	fora(v, l) cout << v << ' ';
	cout << endl;
}

signed main(){
	//freopen(".inp", "r", stdin); freopen(".out", "w", stdout);
	//ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	solve();
}
//hahahahahahahahhaahahahahaahahahaha


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fi first
#define se second
#define for0(i, a, b) for(ll i = a; i < b; ++i)
#define for1(i, a, b) for(ll i = a; i <= b; ++i)
#define forw0(i, a, b) for(ll i = a - 1; i >= b; --i)
#define forw1(i, a, b) for(ll i = a; i >= b; --i)
#define fora(v, a) for(auto v : a)
#define bp __builtin_popcount
#define bpll __builtin_popcountll

typedef vector<int> vi;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<ll> vll;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;

const int mod1 = 1e9 + 7, mod2 = 998244353, maxn = 1e7 + 10, K = 26, maxlog = 19;
const ll infll = 1e18;
const double pi = acos(-1);

/*
1. 1-2 is pivot edge
2. queries -> left or right of pivot edge
3. for each half, find the vertex has the furthest distance to 1-2
4. sort remain points
*/

ll n, area[1010];
vll lef, rig;

bool cmpl(ll x, ll y){
	return area[x] > area[y];
}

bool cmpr(ll x, ll y){
	return area[x] < area[y];
}

void sol(vll &vec){
	if(vec.size() <= 1){
		return;
	}
	ll piv = 0;
	fora(v, vec){
		cout << 1 << ' ' << 1 << ' ' << 2 << ' ' << v << endl;
		ll resp; cin >> resp;
		area[v] = resp;
		if(area[v] > area[piv]){
			piv = v;
		}
	}
	vll l, r;
	fora(v, vec){
		if(v == piv) continue;
		cout << 2 << ' ' << 1 << ' ' << piv << ' ' << v << endl;
		int resp; cin >> resp;
		if(resp == 1) l.pb(v);
		else r.pb(v);
	}
	sort(l.begin(), l.end(), cmpl);
	sort(r.begin(), r.end(), cmpr);
	vec.clear();
	fora(v, r) vec.pb(v);
	vec.pb(piv);
	fora(v, l) vec.pb(v);
}

void solve(){
	cin >> n;
	for1(i, 3, n){
		cout << 2 << ' ' << 1 << ' ' << 2 << ' ' << i << endl;
		int resp; cin >> resp;
		//cross product > 0 means i is to the left of 1-> 2, right otherwise
		if(resp == 1) lef.pb(i);
		else rig.pb(i);
	}
	sol(lef); sol(rig);
	cout << 0 << ' ' << 1 << ' ';
	fora(v, rig) cout << v << ' ';
	cout << 2 << ' ';
	fora(v, lef) cout << v << ' ';
	cout << endl;
}

signed main(){
	//freopen(".inp", "r", stdin); freopen(".out", "w", stdout);
	//ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	solve();
}
//hahahahahahahahhaahahahahaahahahaha


#include <bits/stdc++.h>

#define int long long int
#define pii pair<int,int>
#define vi vector<int>
#define vii vector<pii>
#define mii map<int,int>
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define MOD 1000000007

using namespace std;

int32_t main()
{
    ios_base::sync_with_stdio(false);
    //cin.tie(NULL);

	int n, i, res2, res1;
	cin>>n;
	vii r, l;
	set<pii> ll, lr, rl, rr;
	for (i=3; i<=n; i++)
    {
        cout<<"2 1 2 "<<i<<'\n';
        cin>>res2;
        cout<<"1 1 2 "<<i<<'\n';
        cin>>res1;
        if (res2==-1)
            r.pb({res1,i});
        else
            l.pb({res1,i});
    }
    sort(r.begin(), r.end());
    sort(l.begin(), l.end());
    for (i=0; i<(int)l.size()-1; i++)
    {
        cout<<"2 1 "<<l[l.size()-1].ss<<' '<<l[i].ss<<'\n';
        cin>>res2;
        if (res2==1)
        {
            l[i].ff=-l[i].ff;
            ll.insert(l[i]);
        }
        else
            lr.insert(l[i]);
    }
    for (i=0; i<(int)r.size()-1; i++)
    {
        cout<<"2 1 "<<r[r.size()-1].ss<<' '<<r[i].ss<<'\n';
        cin>>res2;
        if (res2==1)
        {
            r[i].ff=-r[i].ff;
            rl.insert(r[i]);
        }
        else
            rr.insert(r[i]);
    }
    cout<<"0 1 ";
    for (auto it=rr.begin(); it!=rr.end(); it++)
        cout<<it->ss<<' ';
    if (r.size())
        cout<<r[r.size()-1].ss<<' ';
    for (auto it=rl.begin(); it!=rl.end(); it++)
        cout<<it->ss<<' ';
    cout<<"2 ";
    for (auto it=lr.begin(); it!=lr.end(); it++)
        cout<<it->ss<<' ';
    if (l.size())
        cout<<l[l.size()-1].ss<<' ';
    for (auto it=ll.begin(); it!=ll.end(); it++)
        cout<<it->ss<<' ';
}


#include <bits/stdc++.h>

#define int long long int
#define pii pair<int,int>
#define vi vector<int>
#define vii vector<pii>
#define mii map<int,int>
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define MOD 1000000007

using namespace std;

int32_t main()
{
    ios_base::sync_with_stdio(false);
    //cin.tie(NULL);

	int n, i, res2, res1;
	cin>>n;
	vii r, l;
	set<pii> ll, lr, rl, rr;
	for (i=3; i<=n; i++)
    {
        cout<<"2 1 2 "<<i<<'\n';
        cin>>res2;
        cout<<"1 1 2 "<<i<<'\n';
        cin>>res1;
        if (res2==-1)
            r.pb({res1,i});
        else
            l.pb({res1,i});
    }
    sort(r.begin(), r.end());
    sort(l.begin(), l.end());
    for (i=0; i<l.size()-1; i++)
    {
        cout<<"2 1 "<<l[l.size()-1].ss<<' '<<l[i].ss<<'\n';
        cin>>res2;
        if (res2==1)
        {
            l[i].ff=-l[i].ff;
            ll.insert(l[i]);
        }
        else
            lr.insert(l[i]);
    }
    for (i=0; i<r.size()-1; i++)
    {
        cout<<"2 1 "<<r[r.size()-1].ss<<' '<<r[i].ss<<'\n';
        cin>>res2;
        if (res2==1)
        {
            r[i].ff=-r[i].ff;
            rl.insert(r[i]);
        }
        else
            rr.insert(r[i]);
    }
    cout<<"0 1 ";
    for (auto it=rr.begin(); it!=rr.end(); it++)
        cout<<it->ss<<' ';
    if (r.size())
        cout<<r[r.size()-1].ss<<' ';
    for (auto it=rl.begin(); it!=rl.end(); it++)
        cout<<it->ss<<' ';
    cout<<"2 ";
    for (auto it=lr.begin(); it!=lr.end(); it++)
        cout<<it->ss<<' ';
    if (l.size())
        cout<<l[l.size()-1].ss<<' ';
    for (auto it=ll.begin(); it!=ll.end(); it++)
        cout<<it->ss<<' ';
}


#include<bits/stdc++.h>

using namespace std;

using LL = long long;

int n;

int query(int t, int i, int j, int k) {
    cout << t << ' ' << i << ' ' << j << ' ' << k << '\n';
    cout.flush();
    int inp; cin >> inp;
    return inp;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n;

    int a = (query(2, 1, 2, 3) > 0 ? 2 : 3);
    for (int i = 4; i <= n; ++i) {
        a = (query(2, 1, a, i) > 0 ? a : i);
    }

    vector<LL> area(n + 5, 0);
    for (int i = 2; i <= n; ++i) if (i != a) {
        area[i] = query(1, 1, a, i);
    }

    LL maxArea = *max_element(area.begin(), area.end() );

    int b = 0;
    for (int i = 1; i <= n; ++i) if (area[i] == maxArea) {
        b = i;
        break ;
    }

    vector<int> Left, Right;
    for (int i = 2; i <= n; ++i) if (i != a && i != b) {
        if (query(2, 1, b, i) > 0) Left.push_back(i);
        else Right.push_back(i);
    }

    sort(Left.begin(), Left.end(), [&](int i, int j) { return area[i] < area[j]; });
    sort(Right.begin(), Right.end(), [&](int i, int j) { return area[i] > area[j]; });

    cout << "0 1 ";
    for (int _ : Left) cout << _ << ' ';
    cout << b << ' ';
    for (int _ : Right) cout << _ << ' ';
    cout << a;

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using LL = long long;

int n;

LL query(int t, int i, int j, int k) {
    cout << t << ' ' << i << ' ' << j << ' ' << k << '\n';
    cout.flush();
    LL inp; cin >> inp;
    return inp;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n;

    int a = (query(2, 1, 2, 3) > 0 ? 2 : 3);
    for (int i = 4; i <= n; ++i) {
        a = (query(2, 1, a, i) > 0 ? a : i);
    }

    vector<LL> area(n + 5, 0);
    for (int i = 2; i <= n; ++i) if (i != a) {
        area[i] = query(1, 1, a, i);
    }

    LL maxArea = *max_element(area.begin(), area.end() );

    int b = 0;
    for (int i = 1; i <= n; ++i) if (area[i] == maxArea) {
        b = i;
        break ;
    }

    vector<int> Left, Right;
    for (int i = 2; i <= n; ++i) if (i != a && i != b) {
        if (query(2, 1, b, i) > 0) Left.push_back(i);
        else Right.push_back(i);
    }

    sort(Left.begin(), Left.end(), [&](int i, int j) { return area[i] > area[j]; });
    sort(Right.begin(), Right.end(), [&](int i, int j) { return area[i] < area[j]; });

    cout << "0 1 ";
    cout << a << ' ';
    for (int _ : Right) cout << _ << ' ';
    cout << b << ' ';
    for (int _ : Left) cout << _ << ' ';

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using LL = long long;

int n;

int query(int t, int i, int j, int k) {
    cout << t << ' ' << i << ' ' << j << ' ' << k << '\n';
    cout.flush();
    int inp; cin >> inp;
    return inp;
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n;

    int a = (query(2, 1, 2, 3) > 0 ? 2 : 3);
    for (int i = 4; i <= n; ++i) {
        a = (query(2, 1, a, i) > 0 ? a : i);
    }

    vector<LL> area(n + 5, 0);
    for (int i = 2; i <= n; ++i) if (i != a) {
        area[i] = query(1, 1, a, i);
    }

    LL maxArea = *max_element(area.begin(), area.end() );

    int b = 0;
    for (int i = 1; i <= n; ++i) if (area[i] == maxArea) {
        b = i;
        break ;
    }

    vector<int> Left, Right;
    for (int i = 2; i <= n; ++i) if (i != a && i != b) {
        if (query(2, 1, b, i) > 0) Left.push_back(i);
        else Right.push_back(i);
    }

    sort(Left.begin(), Left.end(), [&](int i, int j) { return area[i] > area[j]; });
    sort(Right.begin(), Right.end(), [&](int i, int j) { return area[i] < area[j]; });

    cout << "0 1 ";
    cout << a << ' ';
    for (int _ : Right) cout << _ << ' ';
    cout << b << ' ';
    for (int _ : Left) cout << _ << ' ';

    return 0;
}


#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
namespace IO{
	char ss[1<<17],*A=ss,*B=ss;
	inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	template<class T>inline void In(T&x){
		char c;T y=1;while(c=gc(),!isdigit(c))if(c==45){y=-1;}x=c-48;
		while(c=gc(),isdigit(c)){x=x*10+c-48;}x*=y;
	}
	#define pc(c) sr[++C]=c
	char sr[1<<21],z[20];int C=-1,Z;
	inline void Write(){fwrite(sr,1,C+1,stdout),C=-1;}
	template<class T>inline void Out(T x,char c=' '){
	    if(C>1<<20){Write();}if(x<0){sr[++C]=45,x=-x;}
	    while(z[++Z]=x%10+48,x/=10);
	    while(sr[++C]=z[Z],--Z){};pc(c);
	}
}
using namespace std;
using namespace IO;
const int N=1e6+5,Inf=-1u>>1;
using ll=long long;
using arr=int[N];
/*-----------------------------------------------------------------*/
int n;ll Area[N];
vector<int>Counter,Clockwise,Ans;
inline bool Comp(int a,int b){return Area[a]<Area[b];}
inline ll Qry(int t,int x,int y,int z){
	printf("%d %d %d %d\n",t,x,y,z);
	fflush(stdout);
	ll w;In(w);
	return w;
}
void Solve(vector<int>p,int u){
	if(!p.size())return(void)Ans.push_back(u);
	int Mx=*max_element(p.begin(),p.end(),Comp);
	vector<int>R,L;
	for(auto v:p)if(v!=Mx){
		if(Qry(2,u,Mx,v)==1)
			R.push_back(v);
		else L.push_back(v);
	}
	sort(R.begin(),R.end(),Comp);
	sort(L.begin(),L.end(),Comp);
	reverse(L.begin(),L.end());
	Ans.push_back(u);
	Ans.insert(Ans.end(),R.begin(),R.end());
	Ans.push_back(Mx);
	Ans.insert(Ans.end(),L.begin(),L.end());
}
inline void Sol(){
	In(n);
	fp(i,3,n){
		if(Qry(2,1,2,i)==1)
			Counter.push_back(i);
		else Clockwise .push_back(i);
		Area[i]=Qry(1,1,2,i);
	}
	Solve(Counter,1);
	Solve(Clockwise,2);
	printf("0 ");
	for(auto u:Ans)printf("%d ",u);
	puts("");
	fflush(stdout);
}
int main(){
	#ifndef ONLINE_JUDGE
		file("s");
	#endif
	int T=1;
	while(T--)Sol();
return Write(),0;
}


#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,i##End=b+1;i<i##End;++i)
#define fd(i,a,b) for(register int i=a,i##End=b-1;i>i##End;--i)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
namespace IO{
	// char ss[1<<17],*A=ss,*B=ss;
	// inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	#define gc() getchar()
	template<class T>inline void In(T&x){
		char c;T y=1;while(c=gc(),!isdigit(c))if(c==45){y=-1;}x=c-48;
		while(c=gc(),isdigit(c)){x=x*10+c-48;}x*=y;
	}
	#define pc(c) sr[++C]=c
	char sr[1<<21],z[20];int C=-1,Z;
	inline void Write(){fwrite(sr,1,C+1,stdout),C=-1;}
	template<class T>inline void Out(T x,char c=' '){
	    if(C>1<<20){Write();}if(x<0){sr[++C]=45,x=-x;}
	    while(z[++Z]=x%10+48,x/=10);
	    while(sr[++C]=z[Z],--Z){};pc(c);
	}
}
using namespace std;
using namespace IO;
const int N=1000+5,Inf=-1u>>1;
using ll=long long;
using arr=int[N];
/*-----------------------------------------------------------------*/
int n;ll Area[N];
vector<int>Counter,Clockwise,Ans;
inline bool Comp(int a,int b){return Area[a]<Area[b];}
inline ll Qry(int t,int x,int y,int z){
	printf("%d %d %d %d\n",t,x,y,z);
	fflush(stdout);
	ll w;In(w);
	return w;
}
void Solve(vector<int>p,int u){
	if(!p.size())return(void)Ans.push_back(u);
	int Mx=*max_element(p.begin(),p.end(),Comp);
	vector<int>R,L;
	for(auto v:p)if(v!=Mx){
		if(Qry(2,u,Mx,v)==1)
			R.push_back(v);
		else L.push_back(v);
	}
	sort(R.begin(),R.end(),Comp);
	sort(L.begin(),L.end(),Comp);
	Ans.push_back(u);
	Ans.insert(Ans.end(),L.rbegin(),L.rend());
	Ans.push_back(Mx);
	Ans.insert(Ans.end(),R.begin(),R.end());
}
inline void Sol(){
	In(n);
	fp(i,3,n){
		if(Qry(2,1,2,i)==1)
			Counter.push_back(i);
		else Clockwise .push_back(i);
		Area[i]=Qry(1,1,2,i);
	}
	Solve(Clockwise,1);
	Solve(Counter,2);
	Out(0);
	for(auto u:Ans)Out(u);
}
int main(){
	#ifndef ONLINE_JUDGE
		file("s");
	#endif
	int T=1;
	while(T--)Sol();
return Write(),fflush(stdout),0;
}


#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,i##End=b+1;i<i##End;++i)
#define fd(i,a,b) for(register int i=a,i##End=b-1;i>i##End;--i)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
namespace IO{
	// char ss[1<<17],*A=ss,*B=ss;
	// inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	#define gc() getchar()
	template<class T>inline void In(T&x){
		char c;T y=1;while(c=gc(),!isdigit(c))if(c==45){y=-1;}x=c-48;
		while(c=gc(),isdigit(c)){x=x*10+c-48;}x*=y;
	}
	#define pc(c) sr[++C]=c
	char sr[1<<21],z[20];int C=-1,Z;
	inline void Write(){fwrite(sr,1,C+1,stdout),C=-1;}
	template<class T>inline void Out(T x,char c=' '){
	    if(C>1<<20){Write();}if(x<0){sr[++C]=45,x=-x;}
	    while(z[++Z]=x%10+48,x/=10);
	    while(sr[++C]=z[Z],--Z){};pc(c);
	}
}
using namespace std;
using namespace IO;
const int N=1000+5,Inf=-1u>>1;
using ll=long long;
using arr=int[N];
/*-----------------------------------------------------------------*/
int n;ll Area[N];
vector<int>Counter,Clockwise,Ans;
inline bool Comp(int a,int b){return Area[a]<Area[b];}
inline ll Qry(int t,int x,int y,int z){
	printf("%d %d %d %d\n",t,x,y,z);
	fflush(stdout);
	ll w;In(w);
	return w;
}
void Solve(vector<int>p,int u){
	if(!p.size())return(void)Ans.push_back(u);
	int Mx=*max_element(p.begin(),p.end(),Comp);
	vector<int>R,L;
	for(auto v:p)if(v!=Mx){
		if(Qry(2,u,Mx,v)==1)
			R.push_back(v);
		else L.push_back(v);
	}
	sort(R.begin(),R.end(),Comp);
	sort(L.begin(),L.end(),Comp);
	reverse(L.begin(),L.end());
	Ans.push_back(u);
	Ans.insert(Ans.end(),R.begin(),R.end());
	Ans.push_back(Mx);
	Ans.insert(Ans.end(),L.begin(),L.end());
}
inline void Sol(){
	In(n);
	fp(i,3,n){
		if(Qry(2,1,2,i)==1)
			Counter.push_back(i);
		else Clockwise .push_back(i);
		Area[i]=Qry(1,1,2,i);
	}
	Solve(Counter,1);
	Solve(Clockwise,2);
	Out(0);
	for(auto u:Ans)Out(u);
}
int main(){
	#ifndef ONLINE_JUDGE
		file("s");
	#endif
	int T=1;
	while(T--)Sol();
return Write(),fflush(stdout),0;
}


#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,i##End=b+1;i<i##End;++i)
#define fd(i,a,b) for(register int i=a,i##End=b-1;i>i##End;--i)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
namespace IO{
	// char ss[1<<17],*A=ss,*B=ss;
	// inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
	#define gc() getchar()
	template<class T>inline void In(T&x){
		char c;T y=1;while(c=gc(),!isdigit(c))if(c==45){y=-1;}x=c-48;
		while(c=gc(),isdigit(c)){x=x*10+c-48;}x*=y;
	}
	#define pc(c) sr[++C]=c
	char sr[1<<21],z[20];int C=-1,Z;
	inline void Write(){fwrite(sr,1,C+1,stdout),C=-1;}
	template<class T>inline void Out(T x,char c=' '){
	    if(C>1<<20){Write();}if(x<0){sr[++C]=45,x=-x;}
	    while(z[++Z]=x%10+48,x/=10);
	    while(sr[++C]=z[Z],--Z){};pc(c);
	}
}
using namespace std;
using namespace IO;
const int N=1000+5,Inf=-1u>>1;
using ll=long long;
using arr=int[N];
/*-----------------------------------------------------------------*/
int n;ll Area[N];
vector<int>Counter,Clockwise,Ans;
inline bool Comp(int a,int b){return Area[a]<Area[b];}
inline ll Qry(int t,int x,int y,int z){
	printf("%d %d %d %d\n",t,x,y,z);
	fflush(stdout);
	ll w;In(w);
	return w;
}
void Solve(vector<int>p,int u){
	if(!p.size())return(void)Ans.push_back(u);
	int Mx=*max_element(p.begin(),p.end(),Comp);
	vector<int>R,L;
	for(auto v:p)if(v!=Mx){
		if(Qry(2,u,Mx,v)==1)
			R.push_back(v);
		else L.push_back(v);
	}
	sort(R.begin(),R.end(),Comp);
	sort(L.begin(),L.end(),Comp);
	Ans.push_back(u);
	Ans.insert(Ans.end(),L.begin(),L.end());
	Ans.push_back(Mx);
	Ans.insert(Ans.end(),R.rbegin(),R.rend());
}
inline void Sol(){
	In(n);
	fp(i,3,n){
		if(Qry(2,1,2,i)==1)
			Counter.push_back(i);
		else Clockwise .push_back(i);
		Area[i]=Qry(1,1,2,i);
	}
	Solve(Clockwise,1);
	Solve(Counter,2);
	Out(0);
	for(auto u:Ans)Out(u);
}
int main(){
	#ifndef ONLINE_JUDGE
		file("s");
	#endif
	int T=1;
	while(T--)Sol();
return Write(),fflush(stdout),0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,int> LP;
const int INF=1<<30;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
	for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
	for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
	if(vec_n==-1)vec_n=vec_s.size();
	for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
	if(vec_n==-1)vec_n=vec_s.size();
	for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}

vector<pair<LL,int> > v1,v2;
vector<int> vs;

int main(){
	int n,m;
	LL i,j,k;
	LL a,b,c;
	cin>>n;
	for(i=3;i<=n;i++){
		cout<<1<<" "<<1<<" "<<2<<" "<<i<<endl;
		cin>>a;
		cout<<2<<" "<<1<<" "<<2<<" "<<i<<endl;
		cin>>b;
		if(b==-1)v1.push_back(make_pair(a,i));
		else v2.push_back(make_pair(a,i));
	}
	if(!v1.empty()){
		sort(v1.rbegin(),v1.rend());
		c=2*v1[0].first+1;
		for(i=1;i<v1.size();i++){
			cout<<2<<" "<<1<<" "<<v1[0].second<<" "<<v1[i].second<<endl;
			cin>>b;
			if(b==1)v1[i].first=c-v1[i].first;
		}
		sort(v1.begin(),v1.end());
	}
	if(!v2.empty()){
		sort(v2.rbegin(),v2.rend());
		c=2*v2[0].first+1;
		for(i=1;i<v2.size();i++){
			cout<<2<<" "<<1<<" "<<v2[0].second<<" "<<v2[i].second<<endl;
			cin>>b;
			if(b==1)v2[i].first=c-v2[i].first;
		}
		sort(v2.begin(),v2.end());
	}
	vs.push_back(0);
	vs.push_back(1);
	for(auto node:v1){
		vs.push_back(node.second);
	}
	vs.push_back(2);
	for(auto node:v2){
		vs.push_back(node.second);
	}
	array_show(vs);
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,int> LP;
const int INF=1<<30;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
	for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
	for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
	if(vec_n==-1)vec_n=vec_s.size();
	for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
	if(vec_n==-1)vec_n=vec_s.size();
	for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}

vector<pair<LL,int> > v1,v2;
vector<int> vs;

int main(){
	int n,m;
	LL i,j,k;
	LL a,b,c;
	cin>>n;
	for(i=3;i<=n;i++){
		cout<<1<<" "<<1<<" "<<2<<" "<<i<<endl;
		cin>>a;
		cout<<2<<" "<<1<<" "<<2<<" "<<i<<endl;
		cin>>b;
		if(b==-1)v1.push_back(make_pair(a,i));
		else v2.push_back(make_pair(a,i));
	}
	if(!v1.empty()){
		sort(v1.rbegin(),v1.rend());
		c=3*v1[0].first+1;
		for(i=1;i<v1.size();i++){
			cout<<2<<" "<<1<<" "<<v1[0].second<<" "<<v1[i].second<<endl;
			cin>>b;
			if(b==1)v1[i].first=c-v1[i].first;
		}
		sort(v1.begin(),v1.end());
	}
	if(!v2.empty()){
		sort(v2.rbegin(),v2.rend());
		c=3*v2[0].first+1;
		for(i=1;i<v2.size();i++){
			cout<<2<<" "<<1<<" "<<v2[0].second<<" "<<v2[i].second<<endl;
			cin>>b;
			if(b==1)v2[i].first=c-v2[i].first;
		}
		sort(v2.begin(),v2.end());
	}
	vs.push_back(0);
	vs.push_back(1);
	for(auto node:v1){
		vs.push_back(node.second);
	}
	vs.push_back(2);
	for(auto node:v2){
		vs.push_back(node.second);
	}
	array_show(vs);
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,int> LP;
const int INF=1<<30;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
	for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
	for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
	if(vec_n==-1)vec_n=vec_s.size();
	for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
	if(vec_n==-1)vec_n=vec_s.size();
	for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}

vector<pair<LL,int> > v1,v2;
vector<int> vs;

int main(){
	int n,m;
	LL i,j,k;
	LL a,b,c;
	cin>>n;
	for(i=3;i<=n;i++){
		cout<<1<<" "<<1<<" "<<2<<" "<<i<<flush;
		cin>>a;
		cout<<2<<" "<<1<<" "<<2<<" "<<i<<flush;
		cin>>b;
		if(b==-1)v1.push_back(make_pair(a,i));
		else v2.push_back(make_pair(a,i));
	}
	if(!v1.empty()){
		sort(v1.rbegin(),v1.rend());
		c=2*v1[0].first;
		for(i=1;i<v1.size();i++){
			cout<<2<<" "<<1<<" "<<v1[0].second<<" "<<v1[i].second<<flush;
			cin>>b;
			if(b==1)v1[i].first=c-v1[i].first;
		}
		sort(v1.begin(),v1.end());
	}
	if(!v2.empty()){
		sort(v2.rbegin(),v2.rend());
		c=2*v2[0].first;
		for(i=1;i<v2.size();i++){
			cout<<2<<" "<<1<<" "<<v2[0].second<<" "<<v2[i].second<<flush;
			cin>>b;
			if(b==1)v2[i].first=c-v2[i].first;
		}
		sort(v2.begin(),v2.end());
	}
	vs.push_back(0);
	vs.push_back(1);
	for(auto node:v1){
		vs.push_back(node.second);
	}
	vs.push_back(2);
	for(auto node:v2){
		vs.push_back(node.second);
	}
	array_show(vs);
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<deque>
#include<iomanip>
#include<tuple>
using namespace std;
typedef long long int LL;
typedef pair<int,int> P;
typedef pair<LL,int> LP;
const int INF=1<<30;
const LL MAX=1e9+7;

void array_show(int *array,int array_n,char middle=' '){
	for(int i=0;i<array_n;i++)printf("%d%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(LL *array,int array_n,char middle=' '){
	for(int i=0;i<array_n;i++)printf("%lld%c",array[i],(i!=array_n-1?middle:'\n'));
}
void array_show(vector<int> &vec_s,int vec_n=-1,char middle=' '){
	if(vec_n==-1)vec_n=vec_s.size();
	for(int i=0;i<vec_n;i++)printf("%d%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}
void array_show(vector<LL> &vec_s,int vec_n=-1,char middle=' '){
	if(vec_n==-1)vec_n=vec_s.size();
	for(int i=0;i<vec_n;i++)printf("%lld%c",vec_s[i],(i!=vec_n-1?middle:'\n'));
}

vector<pair<LL,int> > v1,v2;
vector<int> vs;

int main(){
	int n,m;
	LL i,j,k;
	LL a,b,c;
	cin>>n;
	for(i=3;i<=n;i++){
		cout<<1<<" "<<1<<" "<<2<<" "<<i<<endl;
		cin>>a;
		cout<<2<<" "<<1<<" "<<2<<" "<<i<<endl;
		cin>>b;
		if(b==-1)v1.push_back(make_pair(a,i));
		else v2.push_back(make_pair(a,i));
	}
	if(!v1.empty()){
		sort(v1.rbegin(),v1.rend());
		c=2*v1[0].first;
		for(i=1;i<v1.size();i++){
			cout<<2<<" "<<1<<" "<<v1[0].second<<" "<<v1[i].second<<endl;
			cin>>b;
			if(b==1)v1[i].first=c-v1[i].first;
		}
		sort(v1.begin(),v1.end());
	}
	if(!v2.empty()){
		sort(v2.rbegin(),v2.rend());
		c=2*v2[0].first;
		for(i=1;i<v2.size();i++){
			cout<<2<<" "<<1<<" "<<v2[0].second<<" "<<v2[i].second<<endl;
			cin>>b;
			if(b==1)v2[i].first=c-v2[i].first;
		}
		sort(v2.begin(),v2.end());
	}
	vs.push_back(0);
	vs.push_back(1);
	for(auto node:v1){
		vs.push_back(node.second);
	}
	vs.push_back(2);
	for(auto node:v2){
		vs.push_back(node.second);
	}
	array_show(vs);
}


#include <bits/stdc++.h>
#define pi 3.1415926535897932384626
using namespace std;

struct vec
{
    long double x,y;
    bool operator ==(const vec &a) const{
        return x==a.x&&y==a.y;
    }
    bool operator <(const vec &a) const{
        if(a.x!=x) return x<a.x;
        return y<a.y;
    }
    vec operator +(const vec &a) const{
        return {x+a.x,y+a.y};
    }
    vec operator *(const long double &a) const{
        return {x*a,y*a};
    }
    vec operator -(const vec &a) const{
        return {x-a.x,y-a.y};
    }
    vec operator /(const long double &a) const{
        return {x/a,y/a};
    }
    long double len() const{
        return (x*x+y*y);
    }
    long double dot(const vec &a) const{
        return x*a.x+y*a.y;
    }
    long double crs(const vec &a) const{
        return x*a.y-y*a.x;
    }
    vec proj(const vec &a) const{
        return (a/a.len())*(*this).dot(a)/a.len();
    }
};

struct P
{
    int x;
    long long y;
    bool operator <(const P &a) const{
        //if(x!=a.x)
         return x>a.x;

    }
};

bool as(P a,P b)
{
    return a.y<b.y;
}

long long x,y,z,mod=1000000007;
//vector<long long> v,v1;
vector<int> v[22];
//vector<long long> v1;
int i,n,m,k,a,d,b,c,h,dx[10]={1,0,-1,0},dy[10]={0,1,0,-1};
int e;
long long o[1111];

int l[1];

int j[1];
stack<int> s;
//set<int> s;
queue<int> q,q1;
P u[1];
char r[111][111];
//string r,r1;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
//v.resize(unique(v.begin(),v.end())-v.begin());

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//rng();
long long f1(int a,int b,int c)
{
    printf("1 %d %d %d\n",a,b,c);
    fflush(stdout);
    long long x;
    scanf("%lld",&x);
    return x;
}

int f2(int a,int b,int c)
{
    printf("2 %d %d %d\n",a,b,c);
    fflush(stdout);
    int x;
    scanf("%d",&x);
    return x;
}

int main()
{
    scanf("%d",&a);
    for(int t=3;t<=a;t++)
    {
        n=f2(1,2,t);
        if(n<0) v[0].push_back(t);
        else v[1].push_back(t);
    }
    //n=1/0;
    q1.push(0);
    q1.push(1);
    for(int i=0;i<2;i++)
    {
        long long x=-987654321987654321,c=0;
        for(int h=0;h<v[i].size();h++)
            u[h]={v[i][h],f1(1,2,v[i][h])};
        n=1/0;
        sort(u,u+v[i].size(),as);
        for(int h=0;h<v[i].size()-1;h++)
        if(i==0)
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        else
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        q1.push(u[v[i].size()-1].x);
        for(;s.size();s.pop())
            q1.push(s.top());
        if(i==0) q1.push(2);
    }
    //for(;q1.size()>1;q1.pop())
    //    printf("%d ",q1.front());
    //puts("");
    //printf("%d\n",q1.front());
    //fflush(stdout);
}


#include <bits/stdc++.h>
#define pi 3.1415926535897932384626
using namespace std;

struct vec
{
    long double x,y;
    bool operator ==(const vec &a) const{
        return x==a.x&&y==a.y;
    }
    bool operator <(const vec &a) const{
        if(a.x!=x) return x<a.x;
        return y<a.y;
    }
    vec operator +(const vec &a) const{
        return {x+a.x,y+a.y};
    }
    vec operator *(const long double &a) const{
        return {x*a,y*a};
    }
    vec operator -(const vec &a) const{
        return {x-a.x,y-a.y};
    }
    vec operator /(const long double &a) const{
        return {x/a,y/a};
    }
    long double len() const{
        return (x*x+y*y);
    }
    long double dot(const vec &a) const{
        return x*a.x+y*a.y;
    }
    long double crs(const vec &a) const{
        return x*a.y-y*a.x;
    }
    vec proj(const vec &a) const{
        return (a/a.len())*(*this).dot(a)/a.len();
    }
};

struct P
{
    int x;
    long long y;
    bool operator <(const P &a) const{
        //if(x!=a.x)
         return x>a.x;

    }
};

bool as(P a,P b)
{
    return a.y<b.y;
}

long long x,y,z,mod=1000000007;
//vector<long long> v,v1;
vector<int> v[22];
//vector<long long> v1;
int i,n,m,k,a,d,b,c,h,dx[10]={1,0,-1,0},dy[10]={0,1,0,-1};
int e;
long long o[1111];

int l[1];

int j[1];
stack<int> s;
//set<int> s;
queue<int> q,q1;
P u[1];
char r[111][111];
//string r,r1;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
//v.resize(unique(v.begin(),v.end())-v.begin());

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//rng();
long long f1(int a,int b,int c)
{
    printf("1 %d %d %d\n",a,b,c);
    fflush(stdout);
    long long x;
    scanf("%lld",&x);
    return x;
}

int f2(int a,int b,int c)
{
    printf("2 %d %d %d\n",a,b,c);
    fflush(stdout);
    int x;
    scanf("%d",&x);
    return x;
}

int main()
{
    scanf("%d",&a);
    for(int t=3;t<=a;t++)
    {
        n=f2(1,2,t);
        if(n<0) v[0].push_back(t);
        else v[1].push_back(t);
    }
    q1.push(0);
    q1.push(1);
    for(int i=0;i<2;i++)
    {
        long long x=-987654321987654321,c=0;
        for(int h=0;h<v[i].size();h++)
            u[h]={v[i][h],f1(1,2,v[i][h])};
        sort(u,u+v[i].size(),as);
        for(int h=0;h<v[i].size()-1;h++)
        if(i==0)
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        else
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        q1.push(u[v[i].size()-1].x);
        for(;s.size();s.pop())
            q1.push(s.top());
        if(i==0) q1.push(2);
    }
    //for(;q1.size()>1;q1.pop())
    //    printf("%d ",q1.front());
    //puts("");
    //printf("%d\n",q1.front());
    //fflush(stdout);
}


#include <bits/stdc++.h>
#define pi 3.1415926535897932384626
using namespace std;

struct vec
{
    long double x,y;
    bool operator ==(const vec &a) const{
        return x==a.x&&y==a.y;
    }
    bool operator <(const vec &a) const{
        if(a.x!=x) return x<a.x;
        return y<a.y;
    }
    vec operator +(const vec &a) const{
        return {x+a.x,y+a.y};
    }
    vec operator *(const long double &a) const{
        return {x*a,y*a};
    }
    vec operator -(const vec &a) const{
        return {x-a.x,y-a.y};
    }
    vec operator /(const long double &a) const{
        return {x/a,y/a};
    }
    long double len() const{
        return (x*x+y*y);
    }
    long double dot(const vec &a) const{
        return x*a.x+y*a.y;
    }
    long double crs(const vec &a) const{
        return x*a.y-y*a.x;
    }
    vec proj(const vec &a) const{
        return (a/a.len())*(*this).dot(a)/a.len();
    }
};

struct P
{
    int x;
    long long y;
    bool operator <(const P &a) const{
        //if(x!=a.x)
         return x>a.x;

    }
};

bool as(P a,P b)
{
    return a.y<b.y;
}

long long x,y,z,mod=1000000007;
//vector<long long> v,v1;
vector<int> v[22];
//vector<long long> v1;
int i,n,m,k,a,d,b,c,h,dx[10]={1,0,-1,0},dy[10]={0,1,0,-1};
int e;
long long o[1111];

int l[1];

int j[1];
stack<int> s;
//set<int> s;
queue<int> q,q1;
P u[1111];
char r[111][111];
//string r,r1;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
//v.resize(unique(v.begin(),v.end())-v.begin());

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//rng();
long long f1(int a,int b,int c)
{
    //if(c>6) n=1/0;
    //if(b>6)
    printf("1 %d %d %d\n",a,b,c);
    fflush(stdout);
    long long x;
    scanf("%lld",&x);
    return x;
}

int f2(int a,int b,int c)
{
    printf("2 %d %d %d\n",a,b,c);
    fflush(stdout);
    int x;
    scanf("%d",&x);
    return x;
}

int main()
{
    scanf("%d",&a);
    for(int t=3;t<=a;t++)
    {
        n=f2(1,2,t);
        if(n<0) v[0].push_back(t);
        else v[1].push_back(t);
    }
    //n=1/0;
    q1.push(0);
    q1.push(1);
    for(int i=0;i<2;i++)
    //if(v[i])
    {
        for(int h=0;h<v[i].size();h++)
            u[h]={v[i][h],f1(1,2,v[i][h])};
        //n=1/0;
        sort(u,u+v[i].size(),as);
        int dd=v[i].size();
        for(int h=0;h<dd-1;h++)
        if(i==0)
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        else
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        if(v[i].size())
        q1.push(u[v[i].size()-1].x);
        for(;s.size();s.pop())
            q1.push(s.top());
        if(i==0) q1.push(2);
    }
    for(;q1.size()>1;q1.pop())
        printf("%d ",q1.front());
    //puts("");
    printf("%d\n",q1.front());
    fflush(stdout);
}


#include <bits/stdc++.h>
#define pi 3.1415926535897932384626
using namespace std;

struct vec
{
    long double x,y;
    bool operator ==(const vec &a) const{
        return x==a.x&&y==a.y;
    }
    bool operator <(const vec &a) const{
        if(a.x!=x) return x<a.x;
        return y<a.y;
    }
    vec operator +(const vec &a) const{
        return {x+a.x,y+a.y};
    }
    vec operator *(const long double &a) const{
        return {x*a,y*a};
    }
    vec operator -(const vec &a) const{
        return {x-a.x,y-a.y};
    }
    vec operator /(const long double &a) const{
        return {x/a,y/a};
    }
    long double len() const{
        return (x*x+y*y);
    }
    long double dot(const vec &a) const{
        return x*a.x+y*a.y;
    }
    long double crs(const vec &a) const{
        return x*a.y-y*a.x;
    }
    vec proj(const vec &a) const{
        return (a/a.len())*(*this).dot(a)/a.len();
    }
};

struct P
{
    int x;
    long long y;
    bool operator <(const P &a) const{
        //if(x!=a.x)
         return x>a.x;

    }
};

bool as(P a,P b)
{
    return a.y<b.y;
}

long long x,y,z,mod=1000000007;
//vector<long long> v,v1;
vector<int> v[22];
//vector<long long> v1;
int i,n,m,k,a,d,b,c,h,dx[10]={1,0,-1,0},dy[10]={0,1,0,-1};
int e;
long long o[1111];

int l[1];

int j[1];
stack<int> s;
//set<int> s;
queue<int> q,q1;
P u[1];
char r[111][111];
//string r,r1;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
//v.resize(unique(v.begin(),v.end())-v.begin());

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//rng();
long long f1(int a,int b,int c)
{
    if(c>6) n=1/0;
    //if(b>6)
    printf("1 %d %d %d\n",a,b,c);
    fflush(stdout);
    long long x;
    scanf("%lld",&x);
    return x;
}

int f2(int a,int b,int c)
{
    printf("2 %d %d %d\n",a,b,c);
    fflush(stdout);
    int x;
    scanf("%d",&x);
    return x;
}

int main()
{
    scanf("%d",&a);
    for(int t=3;t<=a;t++)
    {
        n=f2(1,2,t);
        if(n<0) v[0].push_back(t);
        else v[1].push_back(t);
    }
    //n=1/0;
    q1.push(0);
    q1.push(1);
    for(int i=0;i<2;i++)
    {
        long long x=-987654321987654321,c=0;
        for(int h=0;h<v[i].size();h++)
            u[h]={v[i][h],f1(1,2,v[i][h])};
        //n=1/0;
        sort(u,u+v[i].size(),as);
        for(int h=0;h<v[i].size()-1;h++)
        if(i==0)
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        else
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        q1.push(u[v[i].size()-1].x);
        for(;s.size();s.pop())
            q1.push(s.top());
        if(i==0) q1.push(2);
    }
    //for(;q1.size()>1;q1.pop())
    //    printf("%d ",q1.front());
    //puts("");
    //printf("%d\n",q1.front());
    //fflush(stdout);
}


#include <bits/stdc++.h>
#define pi 3.1415926535897932384626
using namespace std;

struct vec
{
    long double x,y;
    bool operator ==(const vec &a) const{
        return x==a.x&&y==a.y;
    }
    bool operator <(const vec &a) const{
        if(a.x!=x) return x<a.x;
        return y<a.y;
    }
    vec operator +(const vec &a) const{
        return {x+a.x,y+a.y};
    }
    vec operator *(const long double &a) const{
        return {x*a,y*a};
    }
    vec operator -(const vec &a) const{
        return {x-a.x,y-a.y};
    }
    vec operator /(const long double &a) const{
        return {x/a,y/a};
    }
    long double len() const{
        return (x*x+y*y);
    }
    long double dot(const vec &a) const{
        return x*a.x+y*a.y;
    }
    long double crs(const vec &a) const{
        return x*a.y-y*a.x;
    }
    vec proj(const vec &a) const{
        return (a/a.len())*(*this).dot(a)/a.len();
    }
};

struct P
{
    int x;
    long long y;
    bool operator <(const P &a) const{
        //if(x!=a.x)
         return x>a.x;

    }
};

bool as(P a,P b)
{
    return a.y<b.y;
}

long long x,y,z,mod=1000000007;
//vector<long long> v,v1;
vector<int> v[22];
//vector<long long> v1;
int i,n,m,k,a,d,b,c,h,dx[10]={1,0,-1,0},dy[10]={0,1,0,-1};
int e;
long long o[1111];

int l[1];

int j[1];
stack<int> s;
//set<int> s;
queue<int> q,q1;
P u[1];
char r[111][111];
//string r,r1;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
//v.resize(unique(v.begin(),v.end())-v.begin());

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//rng();
long long f1(int a,int b,int c)
{
    printf("1 %d %d %d\n",a,b,c);
    fflush(stdout);
    long long x;
    scanf("%lld",&x);
    return x;
}

int f2(int a,int b,int c)
{
    printf("2 %d %d %d\n",a,b,c);
    fflush(stdout);
    int x;
    scanf("%d",&x);
    return x;
}

int main()
{
    scanf("%d",&a);
    for(int t=3;t<=a;t++)
    {
        n=f2(1,2,t);
        if(n<0) v[0].push_back(t);
        else v[1].push_back(t);
    }
    n=1/0;
    q1.push(0);
    q1.push(1);
    for(int i=0;i<2;i++)
    {
        long long x=-987654321987654321,c=0;
        for(int h=0;h<v[i].size();h++)
            u[h]={v[i][h],f1(1,2,v[i][h])};
        sort(u,u+v[i].size(),as);
        for(int h=0;h<v[i].size()-1;h++)
        if(i==0)
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        else
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        q1.push(u[v[i].size()-1].x);
        for(;s.size();s.pop())
            q1.push(s.top());
        if(i==0) q1.push(2);
    }
    //for(;q1.size()>1;q1.pop())
    //    printf("%d ",q1.front());
    //puts("");
    //printf("%d\n",q1.front());
    //fflush(stdout);
}


#include <bits/stdc++.h>
#define pi 3.1415926535897932384626
using namespace std;

struct vec
{
    long double x,y;
    bool operator ==(const vec &a) const{
        return x==a.x&&y==a.y;
    }
    bool operator <(const vec &a) const{
        if(a.x!=x) return x<a.x;
        return y<a.y;
    }
    vec operator +(const vec &a) const{
        return {x+a.x,y+a.y};
    }
    vec operator *(const long double &a) const{
        return {x*a,y*a};
    }
    vec operator -(const vec &a) const{
        return {x-a.x,y-a.y};
    }
    vec operator /(const long double &a) const{
        return {x/a,y/a};
    }
    long double len() const{
        return (x*x+y*y);
    }
    long double dot(const vec &a) const{
        return x*a.x+y*a.y;
    }
    long double crs(const vec &a) const{
        return x*a.y-y*a.x;
    }
    vec proj(const vec &a) const{
        return (a/a.len())*(*this).dot(a)/a.len();
    }
};

struct P
{
    int x;
    long long y;
    bool operator <(const P &a) const{
        //if(x!=a.x)
         return x>a.x;

    }
};

bool as(P a,P b)
{
    return a.y<b.y;
}

long long x,y,z,mod=1000000007;
//vector<long long> v,v1;
vector<int> v[22];
//vector<long long> v1;
int i,n,m,k,a,d,b,c,h,dx[10]={1,0,-1,0},dy[10]={0,1,0,-1};
int e;
long long o[1111];

int l[1];

int j[1];
stack<int> s;
//set<int> s;
queue<int> q,q1;
P u[1111];
char r[111][111];
//string r,r1;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
//v.resize(unique(v.begin(),v.end())-v.begin());

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//rng();
long long f1(int a,int b,int c)
{
    //if(c>6) n=1/0;
    //if(b>6)
    printf("1 %d %d %d\n",a,b,c);
    fflush(stdout);
    long long x;
    scanf("%lld",&x);
    return x;
}

int f2(int a,int b,int c)
{
    printf("2 %d %d %d\n",a,b,c);
    fflush(stdout);
    int x;
    scanf("%d",&x);
    return x;
}

int main()
{
    scanf("%d",&a);
    for(int t=3;t<=a;t++)
    {
        n=f2(1,2,t);
        if(n<0) v[0].push_back(t);
        else v[1].push_back(t);
    }
    //n=1/0;
    q1.push(0);
    q1.push(1);
    for(int i=0;i<2;i++)
    {
        long long x=-987654321987654321,c=0;
        for(int h=0;h<v[i].size();h++)
            u[h]={v[i][h],f1(1,2,v[i][h])};
        //n=1/0;
        sort(u,u+v[i].size(),as);
        for(int h=0;h<v[i].size()-1;h++)
        if(i==0)
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        else
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        q1.push(u[v[i].size()-1].x);
        for(;s.size();s.pop())
            q1.push(s.top());
        if(i==0) q1.push(2);
    }
    for(;q1.size()>1;q1.pop())
        printf("%d ",q1.front());
    //puts("");
    printf("%d\n",q1.front());
    fflush(stdout);
}


#include <bits/stdc++.h>
#define pi 3.1415926535897932384626
using namespace std;

struct vec
{
    long double x,y;
    bool operator ==(const vec &a) const{
        return x==a.x&&y==a.y;
    }
    bool operator <(const vec &a) const{
        if(a.x!=x) return x<a.x;
        return y<a.y;
    }
    vec operator +(const vec &a) const{
        return {x+a.x,y+a.y};
    }
    vec operator *(const long double &a) const{
        return {x*a,y*a};
    }
    vec operator -(const vec &a) const{
        return {x-a.x,y-a.y};
    }
    vec operator /(const long double &a) const{
        return {x/a,y/a};
    }
    long double len() const{
        return (x*x+y*y);
    }
    long double dot(const vec &a) const{
        return x*a.x+y*a.y;
    }
    long double crs(const vec &a) const{
        return x*a.y-y*a.x;
    }
    vec proj(const vec &a) const{
        return (a/a.len())*(*this).dot(a)/a.len();
    }
};

struct P
{
    int x;
    long long y;
    bool operator <(const P &a) const{
        //if(x!=a.x)
         return x>a.x;

    }
};

bool as(P a,P b)
{
    return a.y<b.y;
}

long long x,y,z,mod=1000000007;
//vector<long long> v,v1;
vector<int> v[22];
//vector<long long> v1;
int i,n,m,k,a,d,b,c,h,dx[10]={1,0,-1,0},dy[10]={0,1,0,-1};
int e;
long long o[1111];

int l[1];

int j[1];
stack<int> s;
//set<int> s;
queue<int> q,q1;
P u[1];
char r[111][111];
//string r,r1;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
//v.resize(unique(v.begin(),v.end())-v.begin());

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//rng();
long long f1(int a,int b,int c)
{
    printf("1 %d %d %d\n",a,b,c);
    fflush(stdout);
    long long x;
    scanf("%lld",&x);
    return x;
}

int f2(int a,int b,int c)
{
    printf("2 %d %d %d\n",a,b,c);
    fflush(stdout);
    int x;
    scanf("%d",&x);
    return x;
}

int main()
{
    scanf("%d",&a);
    for(int t=3;t<=a;t++)
    {
        n=f2(1,2,t);
        if(n<0) v[0].push_back(t);
        else v[1].push_back(t);
    }
    q1.push(0);
    q1.push(1);
    for(int i=0;i<2;i++)
    {
        long long x=-987654321987654321,c=0;
        for(int h=0;h<v[i].size();h++)
            u[h]={v[i][h],f1(1,2,v[i][h])};
        sort(u,u+v[i].size(),as);
        for(int h=0;h<v[i].size()-1;h++)
        if(i==0)
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        else
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        q1.push(u[v[i].size()-1].x);
        for(;s.size();s.pop())
            q1.push(s.top());
        if(i==0) q1.push(2);
    }
    for(;q1.size();q1.pop())
        printf("%d ",q1.front());
    puts("");
    fflush(stdout);
}


#include <bits/stdc++.h>
#define pi 3.1415926535897932384626
using namespace std;

struct vec
{
    long double x,y;
    bool operator ==(const vec &a) const{
        return x==a.x&&y==a.y;
    }
    bool operator <(const vec &a) const{
        if(a.x!=x) return x<a.x;
        return y<a.y;
    }
    vec operator +(const vec &a) const{
        return {x+a.x,y+a.y};
    }
    vec operator *(const long double &a) const{
        return {x*a,y*a};
    }
    vec operator -(const vec &a) const{
        return {x-a.x,y-a.y};
    }
    vec operator /(const long double &a) const{
        return {x/a,y/a};
    }
    long double len() const{
        return (x*x+y*y);
    }
    long double dot(const vec &a) const{
        return x*a.x+y*a.y;
    }
    long double crs(const vec &a) const{
        return x*a.y-y*a.x;
    }
    vec proj(const vec &a) const{
        return (a/a.len())*(*this).dot(a)/a.len();
    }
};

struct P
{
    int x;
    long long y;
    bool operator <(const P &a) const{
        //if(x!=a.x)
         return x>a.x;

    }
};

bool as(P a,P b)
{
    return a.y<b.y;
}

long long x,y,z,mod=1000000007;
//vector<long long> v,v1;
vector<int> v[22];
//vector<long long> v1;
int i,n,m,k,a,d,b,c,h,dx[10]={1,0,-1,0},dy[10]={0,1,0,-1};
int e;
long long o[1111];

int l[1];

int j[1];
stack<int> s;
//set<int> s;
queue<int> q,q1;
P u[1];
char r[111][111];
//string r,r1;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
//v.resize(unique(v.begin(),v.end())-v.begin());

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//rng();
long long f1(int a,int b,int c)
{
    printf("1 %d %d %d\n",a,b,c);
    fflush(stdout);
    long long x;
    scanf("%lld",&x);
    return x;
}

int f2(int a,int b,int c)
{
    printf("2 %d %d %d\n",a,b,c);
    fflush(stdout);
    int x;
    scanf("%d",&x);
    return x;
}

int main()
{
    scanf("%d",&a);
    for(int t=3;t<=a;t++)
    {
        n=f2(1,2,t);
        if(n<0) v[0].push_back(t);
        else v[1].push_back(t);
    }
    q1.push(0);
    q1.push(1);
    for(int i=0;i<2;i++)
    {
        long long x=-987654321987654321,c=0;
        for(int h=0;h<v[i].size();h++)
            u[h]={v[i][h],f1(1,2,v[i][h])};
        sort(u,u+v[i].size(),as);
        for(int h=0;h<v[i].size()-1;h++)
        if(i==0)
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        else
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        q1.push(u[v[i].size()-1].x);
        for(;s.size();s.pop())
            q1.push(s.top());
        if(i==0) q1.push(2);
    }
    for(;q1.size()>1;q1.pop())
        printf("%d ",q1.front());
    //puts("");
    printf("%d\n",q1.front());
    fflush(stdout);
}


#include <bits/stdc++.h>
#define pi 3.1415926535897932384626
using namespace std;

struct vec
{
    long double x,y;
    bool operator ==(const vec &a) const{
        return x==a.x&&y==a.y;
    }
    bool operator <(const vec &a) const{
        if(a.x!=x) return x<a.x;
        return y<a.y;
    }
    vec operator +(const vec &a) const{
        return {x+a.x,y+a.y};
    }
    vec operator *(const long double &a) const{
        return {x*a,y*a};
    }
    vec operator -(const vec &a) const{
        return {x-a.x,y-a.y};
    }
    vec operator /(const long double &a) const{
        return {x/a,y/a};
    }
    long double len() const{
        return (x*x+y*y);
    }
    long double dot(const vec &a) const{
        return x*a.x+y*a.y;
    }
    long double crs(const vec &a) const{
        return x*a.y-y*a.x;
    }
    vec proj(const vec &a) const{
        return (a/a.len())*(*this).dot(a)/a.len();
    }
};

struct P
{
    int x;
    long long y;
    bool operator <(const P &a) const{
        //if(x!=a.x)
         return x>a.x;

    }
};

bool as(P a,P b)
{
    return a.y<b.y;
}

long long x,y,z,mod=1000000007;
//vector<long long> v,v1;
vector<int> v[22];
//vector<long long> v1;
int i,n,m,k,a,d,b,c,h,dx[10]={1,0,-1,0},dy[10]={0,1,0,-1};
int e;
long long o[1111];

int l[1];

int j[1];
stack<int> s;
//set<int> s;
queue<int> q,q1;
P u[1];
char r[111][111];
//string r,r1;
//2147483647
//'1'==49;
//'A'==65;
//'a'==97;
//unordered_
//map<int,int> p;
//v.resize(unique(v.begin(),v.end())-v.begin());

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//rng();
long long f1(int a,int b,int c)
{
    if(a>6||b>6||c>6) n=1/0;
    //if(b>6)
    printf("1 %d %d %d\n",a,b,c);
    fflush(stdout);
    long long x;
    scanf("%lld",&x);
    return x;
}

int f2(int a,int b,int c)
{
    printf("2 %d %d %d\n",a,b,c);
    fflush(stdout);
    int x;
    scanf("%d",&x);
    return x;
}

int main()
{
    scanf("%d",&a);
    for(int t=3;t<=a;t++)
    {
        n=f2(1,2,t);
        if(n<0) v[0].push_back(t);
        else v[1].push_back(t);
    }
    //n=1/0;
    q1.push(0);
    q1.push(1);
    for(int i=0;i<2;i++)
    {
        long long x=-987654321987654321,c=0;
        for(int h=0;h<v[i].size();h++)
            u[h]={v[i][h],f1(1,2,v[i][h])};
        //n=1/0;
        sort(u,u+v[i].size(),as);
        for(int h=0;h<v[i].size()-1;h++)
        if(i==0)
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        else
        {
            if(f2(1,u[v[i].size()-1].x,u[h].x)>0)
                s.push(u[h].x);
            else q1.push(u[h].x);
        }
        q1.push(u[v[i].size()-1].x);
        for(;s.size();s.pop())
            q1.push(s.top());
        if(i==0) q1.push(2);
    }
    //for(;q1.size()>1;q1.pop())
    //    printf("%d ",q1.front());
    //puts("");
    //printf("%d\n",q1.front());
    //fflush(stdout);
}


#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

vector<pair<long long,int> > Aux[3];
vector<pair<long long,int> > Points[3];
int Rez[1005];

long long ask(int tip, int a, int b, int c)
{
    cout<<tip<<" "<<a<<" "<<b<<" "<<c<<endl;

    long long rez;
    cin>>rez;
    return rez;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin>>n;

    for(int i=3; i<=n; i++)
    {
        long long arie=ask(1,1,2,i);
        int side=ask(2,1,2,i);

        if(side==-1)
            Points[1].push_back({arie,i});
        else
            Points[2].push_back({arie,i});
    }

    int nrez=0;
    for(int i=1; i<=2; i++)
    {
        Rez[++nrez]=i;

        int mx=0,ind=0;
        for(auto point:Points[i])
        {
            if(point.first>mx)
            {
                mx=point.first;
                ind=point.second;
            }
        }

        Aux[1].clear();
        Aux[2].clear();
        for(auto point:Points[i])
        {
            if(point.second==ind)
                continue;
            int side=ask(2,i,ind,point.second);

            if(side==-1)
                Aux[1].push_back(point);
            else
                Aux[2].push_back(point);
        }

        sort(Aux[1].begin(),Aux[1].end());
        sort(Aux[2].begin(),Aux[2].end());

        for(auto point:Aux[1])
            Rez[++nrez]=point.second;
        if(ind!=0)
            Rez[++nrez]=ind;
        for(vector<pair<long long,int> >::reverse_iterator it=Aux[2].rbegin(); it!=Aux[2].rend(); it++)
            Rez[++nrez]=(*it).second;
    }

    cout<<"0 ";
    for(int i=1; i<=n; i++)
        cout<<Rez[i]<<" ";
    cout<<endl;
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

vector<pair<long long,int> > Aux[3];
vector<pair<long long,int> > Points[3];
int Rez[1005];

long long ask(int tip, int a, int b, int c)
{
    cout<<tip<<" "<<a<<" "<<b<<" "<<c<<endl;

    long long rez;
    cin>>rez;
    return rez;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin>>n;

    for(int i=3; i<=n; i++)
    {
        long long arie=ask(1,1,2,i);
        int side=ask(2,1,2,i);

        if(side==-1)
            Points[1].push_back({arie,i});
        else
            Points[2].push_back({arie,i});
    }

    int nrez=0;
    for(int i=1; i<=2; i++)
    {
        Rez[++nrez]=i;

        int mx=0,ind=0;
        for(auto point:Points[i])
        {
            if(point.first>mx)
            {
                mx=point.first;
                ind=point.second;
            }
        }

        Aux[1].clear();
        Aux[2].clear();
        for(auto point:Points[i])
        {
            if(point.second==ind)
                continue;
            int side=ask(2,1,ind,point.second);

            if(side==-1)
                Aux[1].push_back(point);
            else
                Aux[2].push_back(point);
        }

        sort(Aux[1].begin(),Aux[1].end());
        sort(Aux[2].begin(),Aux[2].end());

        for(auto point:Aux[1])
            Rez[++nrez]=point.second;
        if(ind!=0)
            Rez[++nrez]=ind;
        for(vector<pair<long long,int> >::reverse_iterator it=Aux[2].rbegin(); it!=Aux[2].rend(); it++)
            Rez[++nrez]=(*it).second;
    }

    cout<<"0 ";
    for(int i=1; i<=n; i++)
        cout<<Rez[i]<<" ";
    cout<<endl;
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

vector<pair<int,int> > Aux[3];
vector<pair<int,int> > Points[3];
int Rez[1005];

int ask(int tip, int a, int b, int c)
{
    cout<<tip<<" "<<a<<" "<<b<<" "<<c<<endl;

    int rez;
    cin>>rez;
    return rez;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

    int n;
    cin>>n;

    for(int i=3; i<=n; i++)
    {
        int arie=ask(1,1,2,i);
        int side=ask(2,1,2,i);

        if(side==-1)
            Points[1].push_back({arie,i});
        else
            Points[2].push_back({arie,i});
    }

    int nrez=0;
    for(int i=1; i<=2; i++)
    {
        Rez[++nrez]=i;

        int mx=0,ind=0;
        for(auto point:Points[i])
        {
            if(point.first>mx)
            {
                mx=point.first;
                ind=point.second;
            }
        }

        Aux[1].clear();
        Aux[2].clear();
        for(auto point:Points[i])
        {
            if(point.second==ind)
                continue;
            int side=ask(2,1,ind,point.second);

            if(side==-1)
                Aux[1].push_back(point);
            else
                Aux[2].push_back(point);
        }

        sort(Aux[1].begin(),Aux[1].end());
        sort(Aux[2].begin(),Aux[2].end());

        for(auto point:Aux[1])
            Rez[++nrez]=point.second;
        Rez[++nrez]=ind;
        for(vector<pair<int,int> >::reverse_iterator it=Aux[2].rbegin(); it!=Aux[2].rend(); it++)
            Rez[++nrez]=(*it).second;
    }

    cout<<"0 ";
    for(int i=1; i<=n; i++)
        cout<<Rez[i]<<" ";
    cout<<endl;
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

vector<pair<long long,int> > Aux[3];
vector<pair<long long,int> > Points[3];
int Rez[1005];

long long ask(int tip, int a, int b, int c)
{
    cout<<tip<<" "<<a<<" "<<b<<" "<<c<<endl;

    long long rez;
    cin>>rez;
    return rez;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin>>n;

    for(int i=3; i<=n; i++)
    {
        long long arie=ask(1,1,2,i);
        int side=ask(2,1,2,i);

        if(side==-1)
            Points[1].push_back({arie,i});
        else
            Points[2].push_back({arie,i});
    }

    int nrez=0;
    for(int i=1; i<=2; i++)
    {
        Rez[++nrez]=i;

        int mx=0,ind=0;
        for(auto point:Points[i])
        {
            if(point.first>mx)
            {
                mx=point.first;
                ind=point.second;
            }
        }

        Aux[1].clear();
        Aux[2].clear();
        for(auto point:Points[i])
        {
            if(point.second==ind)
                continue;
            int side=ask(2,1,ind,point.second);

            if(side==-1)
                Aux[1].push_back(point);
            else
                Aux[2].push_back(point);
        }

        sort(Aux[1].begin(),Aux[1].end());
        sort(Aux[2].begin(),Aux[2].end());

        for(auto point:Aux[1])
            Rez[++nrez]=point.second;
        Rez[++nrez]=ind;
        for(vector<pair<long long,int> >::reverse_iterator it=Aux[2].rbegin(); it!=Aux[2].rend(); it++)
            Rez[++nrez]=(*it).second;
    }

    cout<<"0 ";
    for(int i=1; i<=n; i++)
        cout<<Rez[i]<<" ";
    cout<<endl;
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

vector<pair<long long,int> > Aux[3];
vector<pair<long long,int> > Points[3];
int Rez[1005];

long long ask(int tip, int a, int b, int c)
{
    cout<<tip<<" "<<a<<" "<<b<<" "<<c<<endl;

    long long rez;
    cin>>rez;
    return rez;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin>>n;

    for(int i=3; i<=n; i++)
    {
        long long arie=ask(1,1,2,i);
        int side=ask(2,1,2,i);

        if(side==-1)
            Points[1].push_back({arie,i});
        else
            Points[2].push_back({arie,i});
    }

    int nrez=0;
    for(int i=1; i<=2; i++)
    {
        Rez[++nrez]=i;

        long long mx=0;
        int ind=0;
        for(auto point:Points[i])
        {
            if(point.first>mx)
            {
                mx=point.first;
                ind=point.second;
            }
        }

        Aux[1].clear();
        Aux[2].clear();
        for(auto point:Points[i])
        {
            if(point.second==ind)
                continue;
            int side=ask(2,i,ind,point.second);

            if(side==-1)
                Aux[1].push_back(point);
            else
                Aux[2].push_back(point);
        }

        sort(Aux[1].begin(),Aux[1].end());
        sort(Aux[2].begin(),Aux[2].end());

        for(auto point:Aux[1])
            Rez[++nrez]=point.second;
        if(ind!=0)
            Rez[++nrez]=ind;
        for(vector<pair<long long,int> >::reverse_iterator it=Aux[2].rbegin(); it!=Aux[2].rend(); it++)
            Rez[++nrez]=(*it).second;
    }

    cout<<"0 ";
    for(int i=1; i<=n; i++)
        cout<<Rez[i]<<" ";
    cout<<endl;
    return 0;
}


#include <iostream>
#include <vector>
#include <array>
#include <list>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <tuple>
#include <bitset>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
#include <cassert>
#include <random>

int main() {
	std::cin.tie(0); std::cin.sync_with_stdio(false);
	int n; std::cin >> n;
	std::vector<long long int> distances(n, 0);
	for (auto i = 2; i < n; ++i) {
		std::cout << "1 1 2 " << i + 1 << std::endl;
		std::cin >> distances[i];
	}
	std::vector<bool> area12(n, false), area_far(n, false);
	for (auto i = 2; i < n; ++i) {
		std::cout << "2 1 2 " << i + 1 << std::endl;
		int sign; std::cin >> sign;
		area12[i] = sign == 1;
	}
	std::vector<int> indices(n); std::iota(indices.begin(), indices.end(), 0);
	const auto true_count = std::count(std::next(area12.begin(), 2), area12.end(), true);
	if (true_count == n - 2 || true_count == 0) {
		auto far = *std::max_element(indices.begin(), indices.end(), [&distances](int i, int j) {return distances[i] < distances[j]; });
		for (auto i = 2; i < n; ++i) if (i != far) {
			std::cout << "2 1 " << far + 1 << ' ' << i + 1 << std::endl;
			int sign; std::cin >> sign;
			area_far[i] = sign == 1;
		}
		std::vector<int> for_false, for_true;
		for (auto i = 2; i < n; ++i) if (i != far) {
			if (area_far[i]) for_true.push_back(i);
			else for_false.push_back(i);
		}
		std::sort(for_false.begin(), for_false.end(), [&distances](int i, int j) {return distances[i] < distances[j]; });
		std::sort(for_true.begin(), for_true.end(), [&distances](int i, int j) {return distances[i] > distances[j]; });
		if (true_count == n - 2) {
			std::cout << "0 1 2";
		}
		else {
			std::cout << "0 2 1";
		}
		for (auto f : for_false) {
			std::cout << " " << f + 1;
		}
		std::cout << " " << far + 1;
		for (auto t : for_true) {
			std::cout << " " << t + 1;
		}
		std::cout << std::endl;
	}
	else {
		int far1 = 0, far2 = 0;
		for (auto i = 2; i < n; ++i) {
			if (area12[i]) {
				if (distances[far1] < distances[i]) {
					far1 = i;
				}
			}
			else {
				if (distances[far2] < distances[i]) {
					far2 = i;
				}
			}
		}
		for (auto i = 2; i < n; ++i) if (i != far1 && i != far2) {
			std::cout << "2 " << far2 + 1 << ' ' << far1 + 1 << ' ' << i + 1 << std::endl;
			int sign; std::cin >> sign;
			area_far[i] = sign == 1;
		}
		std::vector<int> for_true_false, for_true_true, for_false_true, for_false_false;
		for (auto i = 2; i < n; ++i) if (i != far1 && i != far2) {
			if (area12[i]) {
				if (area_far[i]) for_true_true.push_back(i);
				else for_true_false.push_back(i);
			}
			else {
				if (area_far[i]) for_false_true.push_back(i);
				else for_false_false.push_back(i);
			}
		}
		std::cout << "0 " << 2;
		for (auto tf : for_true_false) {
			std::cout << ' ' << tf + 1;
		}
		std::cout << ' ' << far1 + 1;
		for (auto tt : for_true_true) {
			std::cout << ' ' << tt + 1;
		}
		std::cout << ' ' << 1;
		for (auto ft : for_false_true) {
			std::cout << ' ' << ft + 1;
		}
		std::cout << ' ' << far2 + 1;
		for (auto ff : for_false_false) {
			std::cout << ' ' << ff + 1;
		}
		std::cout << std::endl;
	}
}


#include <iostream>
#include <vector>
#include <array>
#include <list>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <tuple>
#include <bitset>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
#include <cassert>
#include <random>

int main() {
	std::cin.tie(0); std::cin.sync_with_stdio(false);
	int n; std::cin >> n;
	std::vector<long long int> distances(n, 0);
	for (auto i = 2; i < n; ++i) {
		std::cout << "1 1 2 " << i + 1 << std::flush;
		std::cin >> distances[i];
	}
	std::vector<bool> area12(n, false), area_far(n, false);
	for (auto i = 2; i < n; ++i) {
		std::cout << "2 1 2 " << i + 1 << std::flush;
		int sign; std::cin >> sign;
		area12[i] = sign == 1;
	}
	std::vector<int> indices(n); std::iota(indices.begin(), indices.end(), 0);
	const auto true_count = std::count(std::next(area12.begin(), 2), area12.end(), true);
	if (true_count == n - 2 || true_count == 0) {
		auto far = *std::max_element(indices.begin(), indices.end(), [&distances](int i, int j) {return distances[i] < distances[j]; });
		for (auto i = 2; i < n; ++i) if (i != far) {
			std::cout << "2 1 " << far + 1 << ' ' << i + 1 << std::flush;
			int sign; std::cin >> sign;
			area_far[i] = sign == 1;
		}
		std::vector<int> for_false, for_true;
		for (auto i = 2; i < n; ++i) if (i != far) {
			if (area_far[i]) for_true.push_back(i);
			else for_false.push_back(i);
		}
		std::sort(for_false.begin(), for_false.end(), [&distances](int i, int j) {return distances[i] < distances[j]; });
		std::sort(for_true.begin(), for_true.end(), [&distances](int i, int j) {return distances[i] > distances[j]; });
		if (true_count == n - 2) {
			std::cout << "0 1 2";
		}
		else {
			std::cout << "0 2 1";
		}
		for (auto f : for_false) {
			std::cout << " " << f + 1;
		}
		std::cout << " " << far + 1;
		for (auto t : for_true) {
			std::cout << " " << t + 1;
		}
		std::cout << std::flush;
	}
	else {
		int far1 = 0, far2 = 0;
		for (auto i = 2; i < n; ++i) {
			if (area12[i]) {
				if (distances[far1] < distances[i]) {
					far1 = i;
				}
			}
			else {
				if (distances[far2] < distances[i]) {
					far2 = i;
				}
			}
		}
		for (auto i = 2; i < n; ++i) if (i != far1 && i != far2) {
			std::cout << "2 " << far2 + 1 << ' ' << far1 + 1 << ' ' << i + 1 << std::flush;
			int sign; std::cin >> sign;
			area_far[i] = sign == 1;
		}
		std::vector<int> for_true_false, for_true_true, for_false_true, for_false_false;
		for (auto i = 2; i < n; ++i) if (i != far1 && i != far2) {
			if (area12[i]) {
				if (area_far[i]) for_true_true.push_back(i);
				else for_true_false.push_back(i);
			}
			else {
				if (area_far[i]) for_false_true.push_back(i);
				else for_false_false.push_back(i);
			}
		}
		std::cout << "0 " << 2;
		for (auto tf : for_true_false) {
			std::cout << ' ' << tf + 1;
		}
		std::cout << ' ' << far1 + 1;
		for (auto tt : for_true_true) {
			std::cout << ' ' << tt + 1;
		}
		std::cout << ' ' << 1;
		for (auto ft : for_false_true) {
			std::cout << ' ' << ft + 1;
		}
		std::cout << ' ' << far2 + 1;
		for (auto ff : for_false_false) {
			std::cout << ' ' << ff + 1;
		}
		std::cout << std::flush;
	}
}


#include <iostream>
#include <vector>
#include <array>
#include <list>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <tuple>
#include <bitset>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
#include <cassert>
#include <random>

int main() {
	std::cin.tie(0); std::cin.sync_with_stdio(false);
	int n; std::cin >> n;
	std::vector<long long int> distances(n, 0);
	for (auto i = 2; i < n; ++i) {
		std::cout << "1 1 2 " << i + 1 << std::endl;
		std::cin >> distances[i];
	}
	std::vector<bool> area12(n, false), area_far(n, false);
	for (auto i = 2; i < n; ++i) {
		std::cout << "2 1 2 " << i + 1 << std::endl;
		int sign; std::cin >> sign;
		area12[i] = sign == 1;
	}
	std::vector<int> indices(n); std::iota(indices.begin(), indices.end(), 0);
	const auto true_count = std::count(std::next(area12.begin(), 2), area12.end(), true);
	if (true_count == n - 2 || true_count == 0) {
		auto far = *std::max_element(indices.begin(), indices.end(), [&distances](int i, int j) {return distances[i] < distances[j]; });
		for (auto i = 2; i < n; ++i) if (i != far) {
			std::cout << "2 1 " << far + 1 << ' ' << i + 1 << std::endl;
			int sign; std::cin >> sign;
			area_far[i] = sign == 1;
		}
		std::vector<int> for_false, for_true;
		for (auto i = 2; i < n; ++i) if (i != far) {
			if (area_far[i]) for_true.push_back(i);
			else for_false.push_back(i);
		}
		std::sort(for_false.begin(), for_false.end(), [&distances](int i, int j) {return distances[i] < distances[j]; });
		std::sort(for_true.begin(), for_true.end(), [&distances](int i, int j) {return distances[i] > distances[j]; });
		if (true_count == n - 2) {
			std::cout << "0 1 2";
		}
		else {
			std::cout << "0 1";
		}
		for (auto f : for_false) {
			std::cout << " " << f + 1;
		}
		std::cout << " " << far + 1;
		for (auto t : for_true) {
			std::cout << " " << t + 1;
		}
		if (true_count == 0) {
			std::cout << " 2";
		}
		std::cout << std::endl;
	}
	else {
		int far1 = 0, far2 = 0;
		for (auto i = 2; i < n; ++i) {
			if (area12[i]) {
				if (distances[far1] < distances[i]) {
					far1 = i;
				}
			}
			else {
				if (distances[far2] < distances[i]) {
					far2 = i;
				}
			}
		}
		for (auto i = 2; i < n; ++i) if (i != far1 && i != far2) {
			std::cout << "2 " << far2 + 1 << ' ' << far1 + 1 << ' ' << i + 1 << std::endl;
			int sign; std::cin >> sign;
			area_far[i] = sign == 1;
		}
		std::vector<int> for_true_false, for_true_true, for_false_true, for_false_false;
		for (auto i = 2; i < n; ++i) if (i != far1 && i != far2) {
			if (area12[i]) {
				if (area_far[i]) for_true_true.push_back(i);
				else for_true_false.push_back(i);
			}
			else {
				if (area_far[i]) for_false_true.push_back(i);
				else for_false_false.push_back(i);
			}
		}
		std::cout << ' ' << 1;
		for (auto ft : for_false_true) {
			std::cout << ' ' << ft + 1;
		}
		std::cout << ' ' << far2 + 1;
		for (auto ff : for_false_false) {
			std::cout << ' ' << ff + 1;
		}
		std::cout << "0 " << 2;
		for (auto tf : for_true_false) {
			std::cout << ' ' << tf + 1;
		}
		std::cout << ' ' << far1 + 1;
		for (auto tt : for_true_true) {
			std::cout << ' ' << tt + 1;
		}
		std::cout << std::endl;
	}
}