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 java.io.*;
import java.lang.reflect.Array;
import java.math.*;
import java.util.*;

@SuppressWarnings("Duplicates")
// author @mdazmat9

public class codeforces{
    static long abs=1000000007;

    public static void main(String[] args) throws IOException {

        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
        int test = 1;
        for (int ind = 0; ind < test; ind++) {
            out.println("? 1 2");
            out.flush();
            int onetwo=sc.nextInt();

            int [] a=new int[6];


            out.println("? 2 3");
            out.flush();
            int twothree=sc.nextInt();



            out.println("? 3 4");
            out.flush();
         int  threefour=sc.nextInt();


            out.println("? 4 5");
            out.flush();
           int fourfive=sc.nextInt();


            int total=7418880;

            int fivesix=total/(onetwo*threefour);
        int[] b=new int[6];
            b[0]=4 ;b[1]= 8; b[2]=15; b[3]=16; b[4]=23;b[5] =42;
            int one=-1,two=-1,three=-1,four=-1,five=-1,six=-1;
            for(int i=0;i<6;i++){
             for(int j=i+1;j<6;j++){
                 if(b[i]*b[j]==onetwo){
                     one=b[i];
                     two=b[j];

                 }
             }
            }

            for(int i=0;i<6;i++){
                for(int j=i+1;j<6;j++){
                    if(b[i]*b[j]==threefour){
                        three=b[i];
                        four=b[j];

                    }
                }
            }

            for(int i=0;i<6;i++){
                for(int j=i+1;j<6;j++){
                    if(b[i]*b[j]==fivesix){
                        five=b[i];
                        six=b[j];

                    }
                }
            }


            int mul1=onetwo*twothree;

            if(one*three==(mul1/(two*two))){
                a[0]=one;
                a[1]=two;
                a[2]=three;
                a[3]=four;
            }
            else if(two*three==(mul1/(one*one))){
                a[0]=two;
                a[1]=one;
                a[2]=three;
                a[3]=four;
            }
            else if(one*four==(mul1/(two*two))){
                a[0]=one;
                a[1]=two;
                a[2]=four;
                a[3]=three;
            }
            else {
                a[0]=two;
                a[1]=one;
                a[2]=four;
                a[3]=three;
            }

            a[4]=fourfive/a[3];
            a[5]=fivesix/a[4];

                out.print("! ");
                for(int i=0;i<6;i++){
                out.print(a[i]+" ");
                }




        }

        out.flush();
    }

    static class UnionFindTree {

        private int[] par;
        private int[] rank;
        private int g;

        public UnionFindTree(int size) {
            par = new int[size];
            rank = new int[size];
            g = size;
            for (int i = 0; i < size; i++) {
                par[i] = -1;
                rank[i] = 0;
            }
        }

        public int find(int x) {
            if (par[x] < 0)
                return x;
            else
                return par[x] = find(par[x]);
        }

        public void unite(int x, int y) {
            x = find(x);
            y = find(y);
            if (x == y)
                return;
            else if (rank[x] > rank[y]) {
                par[x] += par[y];
                par[y] = x;
            } else {
                par[y] += par[x];
                par[x] = y;
                if (rank[x] == rank[y])
                    rank[y]++;
            }
            g--;
        }

        public int groups() {
            return g;
        }

        public int size(int x) {
            return -par[find(x)];
        }

        public boolean same(int x, int y) {
            return find(x) == find(y);
        }
    }




    public static double logb( double a, double b )
    {
        return Math.log(a) / Math.log(b);
    }

    static long fast_pow(long a, long b) {
        if(b == 0)
            return 1L;

        long val = fast_pow(a, b / 2);

        if(b % 2 == 0)
            return val * val % mod;
        else
            return val * val % mod * a % mod;
    }
    static long mod = (long)1e9 + 7;
    static   void shuffle(int[] a) {
        int n = a.length;
        for(int i = 0; i < n; i++) {
            int r = i + (int) (Math.random() * (n - i));
            int tmp = a[i];
            a[i] = a[r];
            a[r] = tmp;
        }
    }
    static long gcd(long a , long b)
    {
        if(b == 0)
            return a;
        return gcd(b , a % b);
    }

}
class Scanner {
    public BufferedReader reader;
    public StringTokenizer st;

    public Scanner(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        st = null;
    }

    public String next() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                String line = reader.readLine();
                if (line == null) return null;
                st = new StringTokenizer(line);
            } catch (Exception e) {
                throw (new RuntimeException());
            }
        }
        return st.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public long nextLong() {
        return Long.parseLong(next());
    }

    public double nextDouble() {
        return Double.parseDouble(next());
    }
}

class OutputWriter {
    BufferedWriter writer;

    public OutputWriter(OutputStream stream) {
        writer = new BufferedWriter(new OutputStreamWriter(stream));
    }

    public void print(int i) throws IOException {
        writer.write(i);
    }

    public void print(String s) throws IOException {
        writer.write(s);
    }

    public void print(char[] c) throws IOException {
        writer.write(c);
    }

    public void close() throws IOException {
        writer.close();
    }

}
class Pair {
    int x;
    int y;

    // Constructor
    public Pair(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}
class Compare {

    static void compare_x(Pair arr[], int n)
    {
        // Comparator to sort the pair according to second element
        Arrays.sort(arr, new Comparator<Pair>() {
            @Override public int compare(Pair p1, Pair p2)
            {
                return (p1.x - p2.x);
            }
        });
    }
    static void compare_y(Pair arr[], int n)
    {
        // Comparator to sort the pair according to second element
        Arrays.sort(arr, new Comparator<Pair>() {
            @Override public int compare(Pair p1, Pair p2)
            {
                return (p1.y - p2.y);
            }
        });
    }
}

class Graph {

    int V;
    ArrayList<Integer>[] adjListArray;


    // constructor
    Graph(int V) {
        this.V = V;

        adjListArray = new ArrayList[V];

        for (int i = 0; i < V; i++) {
            adjListArray[i] = new ArrayList<>();
        }
    }

    // Adds an edge to an undirected graph
    void addEdge(int src, int dest) {

        adjListArray[src].add(dest);
        adjListArray[dest].add(src);
    }


    void DFSUtil(int v, boolean[] visited,int ind) {
        // Mark the current node as visited and print it
        visited[v] = true;
       // System.out.print(v+" ");
        list[ind].add(v);

        // Recur for all the vertices
        // adjacent to this vertex
        for (int x : adjListArray[v]) {
            if(!visited[x]) DFSUtil(x,visited,ind);
        }

    }
    static  ArrayList[] list;
    void connectedComponents() {
        // Mark all the vertices as not visited
     list=new ArrayList[V];
      for(int i=0;i<V;i++)list[i]=new ArrayList();
        boolean[] visited = new boolean[V];
        int index=0;
        for(int v = 0; v < V; ++v) {
            if(!visited[v]) {
                // print all reachable vertices
                // from v
               DFSUtil(v,visited,index++);
            }
        }
        int [] a=new int[V];
        index=0;
        while (true){
            if(list[index].size()==0)
                break;
            for(int i=0;i<list[index].size();i++){
                a[(int)list[index].get(i)]=list[index].size();
            }
            index++;
        }
        for (int i=0;i<V;i++)
            System.out.print(a[i]+" ");
    }


}