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). 
/**
 * BaZ :D
 */
import java.util.*;
import java.io.*;
import static java.lang.Math.*;

public class ACMIND
{
    static FastReader scan;
    static PrintWriter pw;
    static long MOD = 1_000_000_007;
    static long INF = 1_000_000_000_000_000_000L;
    static long inf = 2_000_000_000;
    public static void main(String[] args) {
        new Thread(null,null,"BaZ",1<<27)
        {
            public void run()
            {
                try
                {
                    solve();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                    System.exit(1);
                }
            }
        }.start();
    }

    static void solve() throws IOException
    {
        scan = new FastReader();
        pw = new PrintWriter(System.out,true);
        StringBuilder sb = new StringBuilder();
        int n = ni();
        int next_couter_clockwise = 2;
        for(int i=3;i<=n;++i) {
            if(query(2,1,next_couter_clockwise,i) < 0) {
                next_couter_clockwise = i;
            }
        }
        //pl("Next Counter Clockwise : " + next_couter_clockwise);
        long areas[] = new long[n+1];
        for(int i=2;i<=n;++i) {
            if(i==next_couter_clockwise) {
                continue;
            }
            areas[i] = query(1, 1,next_couter_clockwise, i);
        }
        long max_area = -1;
        int max_area_at = -1;
        for(int i=1;i<=n;++i) {
            if(areas[i] > max_area) {
                max_area = areas[i];
                max_area_at = i;
            }
        }
        //pl("Max area at : "+max_area_at);
        ArrayList<Point> left = new ArrayList<>();
        ArrayList<Point> right = new ArrayList<>();
        for(int i=2;i<=n;++i) {
            if(i==max_area_at) {
                continue;
            }
            if(query(2,1,max_area_at,i) < 0) {
                left.add(new Point(i, areas[i]));
            }
            else {
                right.add(new Point(i, areas[i]));
            }
        }
        Collections.sort(left);
        Collections.sort(right);
//        pa("left", left);
//        pa("right", right);
        p("0");
        p("1");
        for(Point e : left) {
            p(e.idx);
        }
        p(max_area_at);
        Collections.reverse(right);
        for(Point e : right) {
            p(e.idx);
        }
        pl();
        pw.flush();
        pw.close();
    }
    static class Point implements Comparable<Point> {
        long area;
        int idx;
        Point(int idx, long area) {
            this.area = area;
            this.idx = idx;
        }
        public int compareTo(Point other) {
            if(this.area>other.area) {
                return 1;
            }
            else if(this.area<other.area) {
                return -1;
            }
            return 0;
        }
        public String toString() {
            return "{"+this.idx+","+this.area+"}";
        }
    }
    static long query(int type, int x, int y, int z) throws IOException {
        pl(type+" "+x+" "+y+" "+z);
        pw.flush();
        return nl();
    }
    static int ni() throws IOException
    {
        return scan.nextInt();
    }
    static long nl() throws IOException
    {
        return scan.nextLong();
    }
    static double nd() throws IOException
    {
        return scan.nextDouble();
    }
    static void pl()
    {
        pw.println();
    }
    static void p(Object o)
    {
        pw.print(o+" ");
    }
    static void pl(Object o)
    {
        pw.println(o);
    }
    static void psb(StringBuilder sb)
    {
        pw.print(sb);
    }
    static void pa(String arrayName, Object arr[])
    {
        pl(arrayName+" : ");
        for(Object o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, int arr[])
    {
        pl(arrayName+" : ");
        for(int o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, long arr[])
    {
        pl(arrayName+" : ");
        for(long o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, double arr[])
    {
        pl(arrayName+" : ");
        for(double o : arr)
            p(o);
        pl();
    }
    static void pa(String arrayName, char arr[])
    {
        pl(arrayName+" : ");
        for(char o : arr)
            p(o);
        pl();
    }
    static void pa(String listName, List list)
    {
        pl(listName+" : ");
        for(Object o : list)
            p(o);
        pl();
    }
    static void pa(String arrayName, Object[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(Object o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, int[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(int o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, long[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(long o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, char[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(char o : arr[i])
                p(o);
            pl();
        }
    }
    static void pa(String arrayName, double[][] arr) {
        pl(arrayName+" : ");
        for(int i=0;i<arr.length;++i) {
            for(double o : arr[i])
                p(o);
            pl();
        }
    }
    static class FastReader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public FastReader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public FastReader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[1000000];
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n') break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg) return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ') c = read();
            boolean neg = (c == '-');
            if (neg) c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (c == '.') while ((c = read()) >= '0' && c <= '9') ret += (c - '0') / (div *= 10);
            if (neg) return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1) buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead) fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null) return;
            din.close();
        }
    }
}