// Subtasks:
// _: AC

// phase 1: 3 groups, internally linear
// phase 2: model solution with 2n queries

#include <iostream>
#include <vector>
#include <random>
#include <map>

using namespace std;

mt19937 r_dev(100);

int rnd(int a, int b) {
    return uniform_int_distribution<int>(a, b)(r_dev);
}
template<typename T>
T sample(const vector<T> &x) {
    int s = x.size()-1;
    return x[rnd(0, s)];
}

map<pair<int, int>, bool> cache;

bool ask(int u, int v) {
    bool flip = u > v;
    if (flip) swap(u, v);
    if (cache.count({u, v})) return flip != cache[{u, v}];
    cout << "? " << u << " " << v << endl;
    char ans;
    cin >> ans;
    bool b = ans == '>';
    cache[{u, v}] = b;
    return flip != b;
}

int main() {
    int n, t;
    cin >> n >> t;

    int gs1 = (n + 2) / 3, gs2 = (n + 1) / 3, gs3 = n / 3;
    auto get_group = [=](int x) {
      if (x <= gs1) return 1;
      if (x <= gs1+gs2) return 2;
      return 3;
    };

    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            int ig = get_group(i);
            int jg = get_group(j);
            bool f;
            if (ig != jg) {
                // 1 -> 2, 2 -> 3, 3 -> 1
                f = (ig == 1 && jg == 2) || (ig == 2 && jg == 3) || (ig == 3 && jg == 1);
            } else {
                f = i < j;
            }
            if (f) cout << '1';
            else cout << '0';
        }
        cout << endl;
    }

    for (int ti = 0; ti < t; ++ti) {
        cache.clear();
        int rep1 = 1, rep2, rep3;
        vector<int> ts[2];
        for (int i = 2; i <= n; ++i) {
            ts[ask(rep1, i)].push_back(i);
        }
        while (true) {
            int c2 = sample(ts[0]), c3 = sample(ts[1]);
            if (c2 == c3) continue;
            int r1 = ask(rep1, c2), r2 = ask(c2, c3), r3 = ask(c3, rep1);
            if (r1 && r2 && r3) {
                rep2 = c2;
                rep3 = c3;
                break;
            } else if (!r1 && !r2 && !r3) {
                rep2 = c3;
                rep3 = c2;
                break;
            }
        }

        vector<int> g(n+1);
        g[rep1] = 1;
        g[rep2] = 2;
        g[rep3] = 3;

        for (int i = 2; i <= n; ++i) {
            if (i == rep2 || i == rep3) continue;
            bool r1 = ask(rep1, i);
            if (r1) {
                // either in 1 or 2
                bool r3 = ask(rep3, i);
                if (r3) g[i] = 1;
                else g[i] = 2;
            } else {
                // either in 1 or 3
                bool r2 = ask(rep2, i);
                if (r2) g[i] = 3;
                else g[i] = 1;
            }
        }

        pair<int, int> edge_in[4] {};
        for (auto [p, d] : cache) {
            if (g[p.first] == g[p.second]) {
                auto pp = p;
                if (!d) swap(pp.first, pp.second);
                edge_in[g[p.first]] = pp;
            }
        }

        vector<int> gl[4];
        for (int i = 1; i <= n; ++i) gl[g[i]].push_back(i);

        for (int gi : {1, 2, 3}) {
            if (int(gl[gi].size()) > gs3) {
                if (!edge_in[gi].first) {
                    int a = gl[gi][0], b = gl[gi][1];
                    if (ask(a, b)) {
                        edge_in[gi] = {a, b};
                    } else {
                        edge_in[gi] = {b, a};
                    }
                }
                erase(gl[gi], edge_in[gi].first);
                erase(gl[gi], edge_in[gi].second);
            } else edge_in[gi] = {0, 0};
        }

        int cg = 1;
        cout << "! ";
        for (int i = 1; i <= n; ++i) {
            if (edge_in[cg].first) {
                cout << edge_in[cg].first << " " << edge_in[cg].second << " ";
                edge_in[cg] = {0, 0};
                i++;
            } else {
                cout << gl[cg].back() << " ";
                gl[cg].pop_back();
            }
            cg = cg == 3 ? 1 : cg+1;
        }
        cout << endl;
    }
}
