Problem: This is an interactive problem.

Khanh has n points on the Cartesian plane, denoted by a_1, a_2, …, a_n. All points' coordinates are integers between -10^9 and 10^9, inclusive. No three points are collinear. He says that these points are vertices of a convex polygon; in other words, there exists a permutation p_1, p_2, …, p_n of integers from 1 to n such that the polygon a_{p_1} a_{p_2} … a_{p_n} is convex and vertices are listed in counter-clockwise order.

Khanh gives you the number n, but hides the coordinates of his points. Your task is to guess the above permutation by asking multiple queries. In each query, you give Khanh 4 integers t, i, j, k; where either t = 1 or t = 2; and i, j, k are three distinct indices from 1 to n, inclusive. In response, Khanh tells you:

  * if t = 1, the area of the triangle a_ia_ja_k multiplied by 2. 
  * if t = 2, the sign of the cross product of two vectors \overrightarrow{a_ia_j} and \overrightarrow{a_ia_k}. 



Recall that the cross product of vector \overrightarrow{a} = (x_a, y_a) and vector \overrightarrow{b} = (x_b, y_b) is the integer x_a ⋅ y_b - x_b ⋅ y_a. The sign of a number is 1 it it is positive, and -1 otherwise. It can be proven that the cross product obtained in the above queries can not be 0.

You can ask at most 3 ⋅ n queries.

Please note that Khanh fixes the coordinates of his points and does not change it while answering your queries. You do not need to guess the coordinates. In your permutation a_{p_1}a_{p_2}… a_{p_n}, p_1 should be equal to 1 and the indices of vertices should be listed in counter-clockwise order.

Interaction

You start the interaction by reading n (3 ≤ n ≤ 1 000) — the number of vertices.

To ask a query, write 4 integers t, i, j, k (1 ≤ t ≤ 2, 1 ≤ i, j, k ≤ n) in a separate line. i, j and k should be distinct.

Then read a single integer to get the answer to this query, as explained above. It can be proven that the answer of a query is always an integer.

When you find the permutation, write a number 0. Then write n integers p_1, p_2, …, p_n in the same line.

After printing a query do not forget to output end of line and flush the output. Otherwise, you will get Idleness limit exceeded. To do this, use:

  * fflush(stdout) or cout.flush() in C++;
  * System.out.flush() in Java;
  * flush(output) in Pascal;
  * stdout.flush() in Python;
  * see documentation for other languages.



Hack format

To hack, use the following format:

The first line contains an integer n (3 ≤ n ≤ 1 000) — the number of vertices.

The i-th of the next n lines contains two integers x_i and y_i (-10^9 ≤ x_i, y_i ≤ 10^9) — the coordinate of the point a_i.

Example

Input


6

15

-1

1

Output


1 1 4 6

2 1 5 6

2 2 1 4

0 1 3 4 2 6 5

Note

The image below shows the hidden polygon in the example:

<image>

The interaction in the example goes as below: 

  * Contestant reads n = 6. 
  * Contestant asks a query with t = 1, i = 1, j = 4, k = 6. 
  * Jury answers 15. The area of the triangle A_1A_4A_6 is 7.5. Note that the answer is two times the area of the triangle. 
  * Contestant asks a query with t = 2, i = 1, j = 5, k = 6. 
  * Jury answers -1. The cross product of \overrightarrow{A_1A_5} = (2, 2) and \overrightarrow{A_1A_6} = (4, 1) is -2. The sign of -2 is -1. 
  * Contestant asks a query with t = 2, i = 2, j = 1, k = 4. 
  * Jury answers 1. The cross product of \overrightarrow{A_2A_1} = (-5, 2) and \overrightarrow{A_2A_4} = (-2, -1) is 1. The sign of 1 is 1. 
  * Contestant says that the permutation is (1, 3, 4, 2, 6, 5). 

Solution (in JAVA):

Solution:
/**
 * @author derrick20
 */
import java.io.*;
import java.util.*;

public class PointOrdering {
    public static void main(String args[]) throws Exception {
        FastScanner sc = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);

        int N = sc.nextInt();

        int A = 1;
        int B = 2;

        // Left and right will contain all other points EXCEPT A AND B
        ArrayList<Pair> left = new ArrayList<>();
        ArrayList<Pair> right = new ArrayList<>();

        Pair farLeft = new Pair(-1, 0);
        Pair farRight = new Pair(-1, 0);
        for (int i = 3; i <= N; i++) {
            out.println(2 + " " + A + " " + B + " " + i);
            out.flush();
            int sign = sc.nextInt();

            out.println(1 + " " + A + " " + B + " " + i);
            out.flush();
            long area = sc.nextLong();

            Pair p = new Pair(i, area);
            if (sign > 0) {
                right.add(p);
                if (area > farRight.val) {
                    farRight = p;
                }
            }
            else {
                left.add(p);
                if (area > farLeft.val) {
                    farLeft = p;
                }
            }
        }

        // These will contain all points except TOP, BOTTOM, LEFT, RIGHT
        ArrayList<Pair> topRight = new ArrayList<>();
        ArrayList<Pair> bottomRight = new ArrayList<>();

        for (Pair p : right) {
            if (p.idx != farRight.idx) {
                out.println(2 + " " + A + " " + farRight.idx + " " + p.idx);
                out.flush();

                int sign = sc.nextInt();
                if (sign > 0) {
                    topRight.add(p);
                }
                else {
                    bottomRight.add(p);
                }
            }
        }

        ArrayList<Pair> topLeft = new ArrayList<>();
        ArrayList<Pair> bottomLeft = new ArrayList<>();

        for (Pair p : left) {
            if (p.idx != farLeft.idx) {
                out.println(2 + " " + A + " " + farLeft.idx + " " + p.idx);
                out.flush();

                int sign = sc.nextInt();
                // THIS IS THE OPPOSITE OF BEFORE,
                // since it's mirrored!!
                if (sign < 0) {
                    topLeft.add(p);
                }
                else {
                    bottomLeft.add(p);
                }
            }
        }
/*
6
-1
10
-1
8
1
10
1
8
-1
1
 */
        // Make topLeft increasing order,
        // bottomLeft decreasing.
        // bottomRight increasing,
        // topRight decreasing
        Collections.sort(topLeft);
        Collections.sort(bottomLeft, Collections.reverseOrder());
        Collections.sort(bottomRight);
        Collections.sort(topRight, Collections.reverseOrder());

        StringBuilder sb = new StringBuilder("0 ");
        sb.append(A + " ");
        for (Pair p : topLeft) {
            sb.append(p.idx + " ");
        }
        if (farLeft.idx != -1) {
            // There actually had to be stuff between A and B for this
            // to be possible
            sb.append(farLeft.idx + " ");
        }
        for (Pair p : bottomLeft) {
            sb.append(p.idx + " ");
        }
        sb.append(B + " ");
        for (Pair p : bottomRight) {
            sb.append(p.idx + " ");
        }
        if (farRight.idx != -1) {
            sb.append(farRight.idx + " ");
        }
        for (Pair p : topRight) {
            sb.append(p.idx + " ");
        }
        out.println(sb);
        out.flush();
        out.close();
    }

    static class Pair implements Comparable<Pair> {
        int idx;
        long val;
        public Pair(int i, long v) {
            idx = i; val = v;
        }
        public int compareTo(Pair p2) {
            return val - p2.val < 0 ? -1 : 1;
        }
        public String toString() {
            return "(" + idx + ", " + val + ")";
        }
    }

    static class FastScanner {
        public int BS = 1<<16;
        public char NC = (char)0;
        byte[] buf = new byte[BS];
        int bId = 0, size = 0;
        char c = NC;
        double cnt = 1;
        BufferedInputStream in;

        public FastScanner() {
            in = new BufferedInputStream(System.in, BS);
        }

        public FastScanner(String s) {
            try {
                in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
            }
            catch (Exception e) {
                in = new BufferedInputStream(System.in, BS);
            }
        }

        private char getChar(){
            while(bId==size) {
                try {
                    size = in.read(buf);
                }catch(Exception e) {
                    return NC;
                }
                if(size==-1)return NC;
                bId=0;
            }
            return (char)buf[bId++];
        }

        public int nextInt() {
            return (int)nextLong();
        }

        public int[] nextInts(int N) {
            int[] res = new int[N];
            for (int i = 0; i < N; i++) {
                res[i] = (int) nextLong();
            }
            return res;
        }

        public long[] nextLongs(int N) {
            long[] res = new long[N];
            for (int i = 0; i < N; i++) {
                res[i] = nextLong();
            }
            return res;
        }

        public long nextLong() {
            cnt=1;
            boolean neg = false;
            if(c==NC)c=getChar();
            for(;(c<'0' || c>'9'); c = getChar()) {
                if(c=='-')neg=true;
            }
            long res = 0;
            for(; c>='0' && c <='9'; c=getChar()) {
                res = (res<<3)+(res<<1)+c-'0';
                cnt*=10;
            }
            return neg?-res:res;
        }

        public double nextDouble() {
            double cur = nextLong();
            return c!='.' ? cur:cur+nextLong()/cnt;
        }

        public String next() {
            StringBuilder res = new StringBuilder();
            while(c<=32)c=getChar();
            while(c>32) {
                res.append(c);
                c=getChar();
            }
            return res.toString();
        }

        public String nextLine() {
            StringBuilder res = new StringBuilder();
            while(c<=32)c=getChar();
            while(c!='\n') {
                res.append(c);
                c=getChar();
            }
            return res.toString();
        }

        public boolean hasNext() {
            if(c>32)return true;
            while(true) {
                c=getChar();
                if(c==NC)return false;
                else if(c>32)return true;
            }
        }
    }
}