Problem: This is an interactive problem. Remember to flush your output while communicating with the testing program. You may use fflush(stdout) in C++, system.out.flush() in Java, stdout.flush() in Python or flush(output) in Pascal to flush the output. If you use some other programming language, consult its documentation. You may also refer to the guide on interactive problems: <https://codeforces.com/blog/entry/45307>.

The jury guessed some array a consisting of 6 integers. There are 6 special numbers — 4, 8, 15, 16, 23, 42 — and each of these numbers occurs in a exactly once (so, a is some permutation of these numbers).

You don't know anything about their order, but you are allowed to ask up to 4 queries. In each query, you may choose two indices i and j (1 ≤ i, j ≤ 6, i and j are not necessarily distinct), and you will get the value of a_i ⋅ a_j in return.

Can you guess the array a?

The array a is fixed beforehand in each test, the interaction program doesn't try to adapt to your queries.

Interaction

Before submitting the answer, you may ask up to 4 queries. To ask a query, print one line in the following format: ? i j, where i and j should be two integers such that 1 ≤ i, j ≤ 6. The line should be ended with a line break character. After submitting a query, flush the output and read the answer to your query — one line containing one integer a_i ⋅ a_j. If you submit an incorrect query (or ask more than 4 queries), the answer to it will be one string 0. After receiving such an answer, your program should terminate immediately — otherwise you may receive verdict "Runtime error", "Time limit exceeded" or some other verdict instead of "Wrong answer".

To give the answer, your program should print one line ! a_1 a_2 a_3 a_4 a_5 a_6 with a line break in the end. After that, it should flush the output and terminate gracefully.

Example

Input


16
64
345
672

Output


? 1 1
? 2 2
? 3 5
? 4 6
! 4 8 15 16 23 42

Note

If you want to submit a hack for this problem, your test should contain exactly six space-separated integers a_1, a_2, ..., a_6. Each of 6 special numbers should occur exactly once in the test. The test should be ended with a line break character.

Solution (in JAVA):

Solution:
import javax.print.DocFlavor;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import java.io.*;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.nio.Buffer;
import java.sql.BatchUpdateException;
import java.util.*;
import java.util.stream.Stream;
import java.util.Vector;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import static java.lang.Math.*;
import java.util.*;
import java.nio.file.StandardOpenOption;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Iterator;
import java.util.PriorityQueue;

public class icpc
{
    static int a;
    static int b;
    public static void main(String[] args)throws IOException
    {
        //Reader in = new Reader();
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int x = 0;
        int y = 0;
        int z = 0;
        int w = 0;
        int common = 0;
        int left = 0;
        int right = 0;
        int[] finalans = new int[6];
        System.out.println("? 1 2");
        System.out.flush();
        int p = Integer.parseInt(in.readLine());
        get(p);
        x = a;
        y = b;
        System.out.println("? 2 3");
        System.out.flush();
        p = Integer.parseInt(in.readLine());
        get(p);
        z = a;
        w = b;
        if(x == z)
        {
            finalans[0] = y;
            finalans[1] = x;
            finalans[2] = w;
        }
        else if(x == w)
        {
            finalans[0] = y;
            finalans[1] = x;
            finalans[2] = z;
        }
        else if(y == z)
        {
            finalans[0] = x;
            finalans[1] = y;
            finalans[2] = w;
        }
        else if(y == w)
        {
            finalans[0] = x;
            finalans[1] = y;
            finalans[2] = z;
        }
        System.out.println("? 4 5");
        System.out.flush();
        p = Integer.parseInt(in.readLine());
        get(p);
        x = a;
        y = b;
        System.out.println("? 5 6");
        System.out.flush();
        p = Integer.parseInt(in.readLine());
        get(p);
        z = a;
        w = b;
        if(x == z)
        {
            finalans[3] = y;
            finalans[4] = x;
            finalans[5] = w;
        }
        else if(x == w)
        {
            finalans[3] = y;
            finalans[4] = x;
            finalans[5] = z;
        }
        else if(y == z)
        {
            finalans[3] = x;
            finalans[4] = y;
            finalans[5] = w;
        }
        else if(y == w)
        {
            finalans[3] = x;
            finalans[4] = y;
            finalans[5] = z;
        }
        System.out.print("! ");
        for(int i=0;i<6;i++)
            System.out.print(finalans[i] + " ");
        System.out.flush();

    }
    public static void get(int p)
    {
        switch(p)
        {
            case 32: a = 4;b = 8;
            break;
            case 60: a = 4;b = 15;
                break;
            case 64: a = 4;b = 16;
                break;
            case 92: a = 4;b = 23;
                break;
            case 168: a = 4;b = 42;
                break;
            case 120: a = 8;b = 15;
                break;
            case 128: a = 8;b = 16;
                break;
            case 184: a = 8;b = 23;
                break;
            case 336: a = 8;b = 42;
                break;
            case 240: a = 15;b = 16;
                break;
            case 345: a = 15;b = 23;
                break;
            case 630: a = 15;b = 42;
                break;
            case 368: a = 16;b = 23;
                break;
            case 672: a = 16;b = 42;
                break;
            case 966: a = 23;b = 42;
                break;
        }
    }
}
class Matrix
{
    long a;
    long b;
    long c;
    long d;

    public Matrix(long a, long b, long c, long d)
    {
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
    }
}
class Game
{
    int x;
    int y;
    char d;

    public Game(int x, int y, char d)
    {
        this.x = x;
        this.y = y;
        this.d = d;
    }
}
class MergeSort
{
    // Merges two subarrays of arr[].
    // First subarray is arr[l..m]
    // Second subarray is arr[m+1..r]
    void merge(int arr[], int l, int m, int r) {
        // Find sizes of two subarrays to be merged
        int n1 = m - l + 1;
        int n2 = r - m;

        /* Create temp arrays */
        int L[] = new int[n1];
        int R[] = new int[n2];

        /*Copy data to temp arrays*/
        for (int i = 0; i < n1; ++i)
            L[i] = arr[l + i];
        for (int j = 0; j < n2; ++j)
            R[j] = arr[m + 1 + j];


        /* Merge the temp arrays */

        // Initial indexes of first and second subarrays
        int i = 0, j = 0;

        // Initial index of merged subarry array
        int k = l;
        while (i < n1 && j < n2) {
            if (L[i] <= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
            k++;
        }

        /* Copy remaining elements of L[] if any */
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }

        /* Copy remaining elements of R[] if any */
        while (j < n2) {
            arr[k] = R[j];
            j++;
            k++;
        }
    }

    // Main function that sorts arr[l..r] using
    // merge()
    void sort(int arr[], int l, int r) {
        if (l < r) {
            // Find the middle point
            int m = (l + r) / 2;

            // Sort first and second halves
            sort(arr, l, m);
            sort(arr, m + 1, r);

            // Merge the sorted halves
            merge(arr, l, m, r);
        }
    }

}
class Node
{
    String a;
    String b;
    Node(String s1,String s2)
    {
        this.a = s1;
        this.b = s2;
    }
    @Override
    public boolean equals(Object ob)
    {
        if(ob == null)
            return false;
        if(!(ob instanceof Node))
            return false;
        if(ob == this)
            return true;
        Node obj = (Node)ob;
        if(this.a.equals(obj.a) && this.b.equals(obj.b))
            return true;
        return false;
    }

    @Override
    public int hashCode()
    {
        return (int)this.a.length();
    }
}
class Reader
{
    final private int BUFFER_SIZE = 1 << 16;
    private DataInputStream din;
    private byte[] buffer;
    private int bufferPointer, bytesRead;

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

    public Reader(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[64]; // line length
        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();
    }
}
class Hey
{
    public static int multTwoNumbers(int a, int b, int n)
    {
        if(a == 0)
            return 0;
        else if(a % 2 == 0)
            return (2 * ((multTwoNumbers(a / 2, b, n)) % n))% n;
        else
            return ((2 * ((multTwoNumbers((a - 1) / 2, b, n)) % n))% n + b) % n;
    }
    public static long binPow(long a, long n)
    {
        long res = 1L;
        while (n > 0)
        {
            if((n & 1) > 0)
            {
                res *= a;
            }
            a *= a;
            n >>= 1;
        }
        return res;
    }
    public static long phi(long n)
    {
        long result = n;
        for(int i=2;i*i <= n;i++)
        {
            if(n % i == 0)
            {
                while(n % i == 0)
                    n = n / i;
                result -= result / (long)i;
            }
        }
        if(n > 1)
            result -= result / n;
        return result;
    }
}
class FenwickTree
{
    public void update(long[] fenwickTree,long delta,int index)
    {
        index += 1;
        while(index < fenwickTree.length)
        {
            fenwickTree[index] += delta;
            index = index + (index & (-index));
        }
    }
    public long prefixSum(long[] fenwickTree,int index)
    {
        long sum = 0L;
        index += 1;
        while(index > 0)
        {
            sum += fenwickTree[index];
            index -= (index & (-index));
        }
        return sum;
    }
}
class SegmentTree
{
    public int nextPowerOfTwo(int num)
    {
        if(num == 0)
            return 1;
        if(num > 0 && (num & (num - 1)) == 0)
            return num;
        while((num &(num - 1)) > 0)
        {
            num = num & (num - 1);
        }
        return num << 1;
    }
    public int[] createSegmentTree(int[] input)
    {
        int np2 = nextPowerOfTwo(input.length);
        int[] segmentTree = new int[np2 * 2 - 1];

        for(int i=0;i<segmentTree.length;i++)
            segmentTree[i] = Integer.MIN_VALUE;

        constructSegmentTree(segmentTree,input,0,input.length-1,0);
        return segmentTree;

    }
    private void constructSegmentTree(int[] segmentTree,int[] input,int low,int high,int pos)
    {
        if(low == high)
        {
            segmentTree[pos] = input[low];
            return;
        }
        int mid = (low + high)/ 2;
        constructSegmentTree(segmentTree,input,low,mid,2*pos + 1);
        constructSegmentTree(segmentTree,input,mid+1,high,2*pos + 2);
        segmentTree[pos] = Math.max(segmentTree[2*pos + 1],segmentTree[2*pos + 2]);
    }
    public int rangeMinimumQuery(int []segmentTree,int qlow,int qhigh,int len)
    {
        return rangeMinimumQuery(segmentTree,0,len-1,qlow,qhigh,0);
    }
    private int rangeMinimumQuery(int segmentTree[],int low,int high,int qlow,int qhigh,int pos)
    {
        if(qlow <= low && qhigh >= high){
            return segmentTree[pos];
        }
        if(qlow > high || qhigh < low){
            return Integer.MIN_VALUE;
        }
        int mid = (low+high)/2;
        return Math.max(rangeMinimumQuery(segmentTree, low, mid, qlow, qhigh, 2 * pos + 1),
                rangeMinimumQuery(segmentTree, mid + 1, high, qlow, qhigh, 2 * pos + 2));
    }
}
class Point
{
    long x;
    long y;
    Point(long a, long b)
    {
        this.x = a;
        this.y = b;
    }
}