#include <bits/stdc++.h>
using namespace std;

// Datacenter Imprisonment / Midnight Code Cup
// Adaptive-frontier mapper for the supplied Kruskal room-grid generator.
//
// Odd/odd cells are rooms; the only unknown cells are the walls between adjacent
// rooms.  The normal tuned diagonal schedule is kept as a fallback.  For large
// low-agent cases this branch lets agent 0 inspect the partial tree after each
// reduction, then broadcast the next region to query: either a full diagonal
// expansion or a pair of frontier rectangles around the currently known start
// and goal components.  The final phase always maps every remaining edge, so
// correctness does not depend on the adaptive heuristic.

static string ask_line(const string &q) {
    cout << q << '\n' << flush;
    string r;
    if (!getline(cin, r)) exit(0);
    return r;
}

static inline char enc_digit(int x) {
    return (char)('!' + x);
}

static inline int dec_digit(char ch) {
    return (int)(unsigned char)ch - (int)(unsigned char)'!';
}

static int max_bits_per_message(int max_msg_len) {
    int pairs = max_msg_len / 2;
    int bits = pairs * 13;
    if (max_msg_len % 2) bits += 6;
    return max(1, bits);
}

static inline int h_count(int m) { return m * (m - 1); }
static inline int edge_count(int m) { return 2 * m * (m - 1); }
static inline int idx_h(int r, int c, int m) { return r * (m - 1) + c; }
static inline int idx_v(int r, int c, int m) { return h_count(m) + r * m + c; }

static pair<int,int> query_cell_for_edge(int idx, int m) {
    int H = h_count(m);
    if (idx < H) {
        int r = idx / (m - 1);
        int c = idx % (m - 1);
        return {2 * r + 1, 2 * c + 2};
    }
    int x = idx - H;
    int r = x / m;
    int c = x % m;
    return {2 * r + 2, 2 * c + 1};
}

struct EdgeRooms {
    int r1, c1, r2, c2;
};

static EdgeRooms edge_rooms(int idx, int m) {
    int H = h_count(m);
    if (idx < H) {
        int r = idx / (m - 1);
        int c = idx % (m - 1);
        return {r, c, r, c + 1};
    }
    int x = idx - H;
    int r = x / m;
    int c = x % m;
    return {r, c, r + 1, c};
}

static int edge_diag_margin(int idx, int m) {
    EdgeRooms e = edge_rooms(idx, m);
    return min(abs(e.r1 - e.c1), abs(e.r2 - e.c2));
}

static bool edge_in_diag_band(int idx, int m, int band) {
    return edge_diag_margin(idx, m) <= band;
}

static vector<int> choose_bands(int m, int N, int A) {
    vector<int> pct = {25, 35, 45, 53, 60};

    auto old_schedule = [&]() {
        vector<int> old = {20, 30, 40, 50, 60, 70};
        if (N >= 450 && 15 <= A && A <= 20) old = {53};
        if (N <= 110 && A >= 20) old = {53};
        if (301 <= N && N <= 450 && 12 <= A && A <= 35) {
            old = {25, 37, 50, 63, 76};
        }
        return old;
    };

    // Broad N/A regimes where the older macro-block schedule wins: either
    // communication-heavy small boards or cases where an early 20/30 checkpoint
    // catches enough paths to beat the later global schedule.
    bool use_old = false;
    if (N <= 130 && A >= 20) use_old = true;
    if (A <= 5 && N < 300) use_old = true;
    if (N <= 300 && A <= 10) use_old = true;
    if (150 <= N && N <= 220 && A == 12) use_old = true;
    if (N <= 165 && A >= 40) use_old = true;
    if (190 <= N && N <= 205 && 35 <= A && A <= 38) use_old = true;
    if (230 <= N && N <= 300 && 23 <= A && A <= 26) use_old = true;
    if (250 <= N && N <= 300 && A <= 15) use_old = true;
    if (301 <= N && N <= 450 && A <= 15) use_old = true;
    if (301 <= N && N <= 450 && A >= 36) use_old = true;
    if (N >= 450 && 15 <= A && A <= 20) use_old = true;
    if (N >= 450 && 25 <= A && A <= 40) use_old = true;
    if (use_old) pct = old_schedule();

    vector<int> bands;
    int last = -1;
    for (int p : pct) {
        int b = (p * m + 99) / 100;
        if (b < 2) b = 2;
        if (b > m - 1) b = m - 1;
        if (b > last) {
            bands.push_back(b);
            last = b;
        }
        if (b == m - 1) break;
    }
    return bands;
}

static vector<int> build_edge_order(int m, const vector<int> &bands, vector<int> &counts) {
    int E = edge_count(m);
    vector<vector<int>> groups(bands.size() + 1);
    for (int idx = 0; idx < E; ++idx) {
        size_t g = bands.size();
        for (size_t k = 0; k < bands.size(); ++k) {
            if (edge_in_diag_band(idx, m, bands[k])) {
                g = k;
                break;
            }
        }
        groups[g].push_back(idx);
    }
    vector<int> order;
    order.reserve(E);
    counts.clear();
    counts.reserve(groups.size());
    for (auto &v : groups) {
        counts.push_back((int)v.size());
        order.insert(order.end(), v.begin(), v.end());
    }
    return order;
}

static int local_count_for_sender(int sender, int count, int A) {
    if (sender < 0 || sender >= A || sender >= count) return 0;
    return 1 + (count - 1 - sender) / A;
}

static long long block_count_for_senders(int l, int r, int count, int A) {
    r = min(r, A);
    long long s = 0;
    for (int p = l; p < r; ++p) s += local_count_for_sender(p, count, A);
    return s;
}

static vector<unsigned char> query_phase(int start, int count,
                                         const vector<int> &order,
                                         int m, int A, int ID) {
    vector<unsigned char> bits;
    bits.reserve(local_count_for_sender(ID, count, A));
    for (int pos = ID; pos < count; pos += A) {
        auto [r, c] = query_cell_for_edge(order[start + pos], m);
        string rep = ask_line("? " + to_string(r) + " " + to_string(c));
        bits.push_back(!rep.empty() && rep[0] == '1');
    }
    return bits;
}

static string pack_bits(const vector<unsigned char> &bits, long long start, int len) {
    string body;
    body.reserve((len * 2 + 12) / 13);
    int p = 0;
    while (len - p >= 13) {
        int v = 0;
        for (int k = 0; k < 13; ++k) {
            if (bits[(size_t)start + p + k]) v |= (1 << k);
        }
        body.push_back(enc_digit(v % 94));
        body.push_back(enc_digit(v / 94));
        p += 13;
    }
    int rem = len - p;
    if (rem > 0) {
        int v = 0;
        for (int k = 0; k < rem; ++k) {
            if (bits[(size_t)start + p + k]) v |= (1 << k);
        }
        body.push_back(enc_digit(v % 94));
        if (rem > 6) body.push_back(enc_digit(v / 94));
    }
    return body;
}

static void send_bit_vector(int target, const vector<unsigned char> &bits, int bits_per_msg) {
    long long total = (long long)bits.size();
    for (long long pos = 0; pos < total; pos += bits_per_msg) {
        int len = (int)min<long long>(bits_per_msg, total - pos);
        string body = pack_bits(bits, pos, len);
        (void)ask_line("> " + to_string(target) + " " + body);
    }
}

static vector<unsigned char> receive_bit_vector_from(int sender, long long expected_bits,
                                                     int bits_per_msg) {
    vector<unsigned char> got;
    if (expected_bits <= 0) return got;
    got.reserve((size_t)expected_bits);
    while ((long long)got.size() < expected_bits) {
        string rep = ask_line("< " + to_string(sender));
        if (rep == "- -" || rep.empty()) continue;
        size_t sp = rep.find(' ');
        if (sp == string::npos) continue;
        int actual = atoi(rep.substr(0, sp).c_str());
        if (actual != sender) continue;
        string body = rep.substr(sp + 1);
        long long remaining = expected_bits - (long long)got.size();
        int need = (int)min<long long>(bits_per_msg, remaining);
        int pos = 0;
        int produced = 0;
        while (need - produced >= 13 && pos + 1 < (int)body.size()) {
            int v = dec_digit(body[pos]) + 94 * dec_digit(body[pos + 1]);
            pos += 2;
            for (int k = 0; k < 13; ++k) {
                got.push_back((unsigned char)((v >> k) & 1));
            }
            produced += 13;
        }
        int rem = need - produced;
        if (rem > 0 && pos < (int)body.size()) {
            int v = dec_digit(body[pos++]);
            if (rem > 6 && pos < (int)body.size()) v += 94 * dec_digit(body[pos++]);
            for (int k = 0; k < rem; ++k) {
                got.push_back((unsigned char)((v >> k) & 1));
            }
            produced += rem;
        }
        while (produced < need) {
            got.push_back(0);
            ++produced;
        }
    }
    return got;
}

static vector<unsigned char> binary_reduce_phase(vector<unsigned char> local_bits,
                                                 int count, int A, int ID,
                                                 int bits_per_msg,
                                                 bool halt_after_send) {
    vector<unsigned char> aggregate;
    aggregate.swap(local_bits);
    for (int width = 1; width < A; width <<= 1) {
        int period = width << 1;
        int rem = ID % period;
        if (rem == 0) {
            int child = ID + width;
            if (child < A) {
                long long need = block_count_for_senders(child, child + width, count, A);
                vector<unsigned char> rhs = receive_bit_vector_from(child, need, bits_per_msg);
                aggregate.insert(aggregate.end(), rhs.begin(), rhs.end());
            }
        } else if (rem == width) {
            int parent = ID - width;
            send_bit_vector(parent, aggregate, bits_per_msg);
            if (halt_after_send) {
                cout << "halt\n" << flush;
                exit(0);
            }
            aggregate.clear();
            return aggregate;
        } else {
            if (halt_after_send) {
                cout << "halt\n" << flush;
                exit(0);
            }
            aggregate.clear();
            return aggregate;
        }
    }
    return aggregate;
}

static void store_aggregate_phase(int start, int count, int A,
                                  const vector<int> &order,
                                  const vector<unsigned char> &aggregate,
                                  vector<unsigned char> &edge_open) {
    long long pos = 0;
    for (int p = 0; p < A; ++p) {
        int cnt = local_count_for_sender(p, count, A);
        for (int j = 0; j < cnt; ++j, ++pos) {
            int seq_pos = p + j * A;
            if (seq_pos >= count || pos >= (long long)aggregate.size()) continue;
            edge_open[order[start + seq_pos]] = aggregate[(size_t)pos];
        }
    }
}

static string solve_from_edges(int N, const vector<unsigned char> &open) {
    int m = (N + 1) / 2;
    int V = m * m;
    if (V == 1) return string();

    vector<int> parent(V, -1);
    vector<char> pmove(V, 0);
    queue<int> q;
    parent[0] = 0;
    q.push(0);

    while (!q.empty()) {
        int u = q.front();
        q.pop();
        if (u == V - 1) break;
        int r = u / m, c = u % m;
        auto add = [&](int nr, int nc, int eidx, char ch) {
            if (nr < 0 || nr >= m || nc < 0 || nc >= m) return;
            if (!open[eidx]) return;
            int v = nr * m + nc;
            if (parent[v] != -1) return;
            parent[v] = u;
            pmove[v] = ch;
            q.push(v);
        };
        if (r > 0)     add(r - 1, c, idx_v(r - 1, c, m), 'U');
        if (c > 0)     add(r, c - 1, idx_h(r, c - 1, m), 'L');
        if (r + 1 < m) add(r + 1, c, idx_v(r, c, m), 'D');
        if (c + 1 < m) add(r, c + 1, idx_h(r, c, m), 'R');
    }

    if (parent[V - 1] == -1) return string();

    string room_path;
    for (int cur = V - 1; cur != 0; cur = parent[cur]) room_path.push_back(pmove[cur]);
    reverse(room_path.begin(), room_path.end());

    string cell_path;
    cell_path.reserve(room_path.size() * 2);
    for (char ch : room_path) {
        cell_path.push_back(ch);
        cell_path.push_back(ch);
    }
    return cell_path;
}

static void claim_answer(const string &ans) {
    if (ans.empty()) cout << "!" << '\n' << flush;
    else cout << "! " << ans << '\n' << flush;
}

struct Rect {
    int r1, r2, c1, c2;
};

struct PhaseSpec {
    char type; // 'D': diagonal prefix, 'R': diagonal prefix clipped to rects, 'F': all remaining
    int hi;
    Rect a, b;
};

static vector<int> split_ints(const string &s) {
    vector<int> out;
    int cur = 0;
    int sign = 1;
    bool in_num = false;
    for (char ch : s) {
        if (ch == '-') {
            sign = -1;
            cur = 0;
            in_num = true;
        } else if ('0' <= ch && ch <= '9') {
            cur = cur * 10 + (ch - '0');
            in_num = true;
        } else if (in_num) {
            out.push_back(sign * cur);
            cur = 0;
            sign = 1;
            in_num = false;
        }
    }
    if (in_num) out.push_back(sign * cur);
    return out;
}

static string encode_phase_spec(const PhaseSpec &s) {
    if (s.type == 'F') return "F";
    if (s.type == 'D') return "D," + to_string(s.hi);
    return "R," + to_string(s.hi) + "," +
           to_string(s.a.r1) + "," + to_string(s.a.r2) + "," +
           to_string(s.a.c1) + "," + to_string(s.a.c2) + "," +
           to_string(s.b.r1) + "," + to_string(s.b.r2) + "," +
           to_string(s.b.c1) + "," + to_string(s.b.c2);
}

static PhaseSpec parse_phase_spec(const string &body) {
    PhaseSpec s;
    s.type = body.empty() ? 'F' : body[0];
    s.hi = 0;
    s.a = s.b = {0, -1, 0, -1};
    vector<int> v = split_ints(body);
    if (s.type == 'D' && !v.empty()) {
        s.hi = v[0];
    } else if (s.type == 'R' && v.size() >= 9) {
        s.hi = v[0];
        s.a = {v[1], v[2], v[3], v[4]};
        s.b = {v[5], v[6], v[7], v[8]};
    } else {
        s.type = 'F';
    }
    return s;
}

static bool in_rect(int r, int c, const Rect &x) {
    return x.r1 <= r && r <= x.r2 && x.c1 <= c && c <= x.c2;
}

static bool edge_touches_rect(int idx, int m, const Rect &x) {
    if (x.r1 > x.r2 || x.c1 > x.c2) return false;
    EdgeRooms e = edge_rooms(idx, m);
    return in_rect(e.r1, e.c1, x) || in_rect(e.r2, e.c2, x);
}

static bool phase_matches(int idx, int m, const PhaseSpec &s) {
    if (s.type == 'F') return true;
    if (edge_diag_margin(idx, m) > s.hi) return false;
    if (s.type == 'D') return true;
    return edge_touches_rect(idx, m, s.a) || edge_touches_rect(idx, m, s.b);
}

static vector<int> build_phase_edges(int m, const PhaseSpec &s,
                                     const vector<unsigned char> &queried) {
    int E = edge_count(m);
    vector<int> edges;
    edges.reserve(E / 4);
    for (int idx = 0; idx < E; ++idx) {
        if (!queried[(size_t)idx] && phase_matches(idx, m, s)) edges.push_back(idx);
    }
    return edges;
}

static vector<unsigned char> query_edge_list(const vector<int> &edges,
                                             int m, int A, int ID) {
    int count = (int)edges.size();
    vector<unsigned char> bits;
    bits.reserve(local_count_for_sender(ID, count, A));
    for (int pos = ID; pos < count; pos += A) {
        auto [r, c] = query_cell_for_edge(edges[(size_t)pos], m);
        string rep = ask_line("? " + to_string(r) + " " + to_string(c));
        bits.push_back(!rep.empty() && rep[0] == '1');
    }
    return bits;
}

static void store_aggregate_edges(const vector<int> &edges, int A,
                                  const vector<unsigned char> &aggregate,
                                  vector<unsigned char> &edge_open) {
    int count = (int)edges.size();
    long long pos = 0;
    for (int p = 0; p < A; ++p) {
        int cnt = local_count_for_sender(p, count, A);
        for (int j = 0; j < cnt; ++j, ++pos) {
            int seq_pos = p + j * A;
            if (seq_pos >= count || pos >= (long long)aggregate.size()) continue;
            edge_open[(size_t)edges[(size_t)seq_pos]] = aggregate[(size_t)pos];
        }
    }
}

static void mark_queried(const vector<int> &edges, vector<unsigned char> &queried) {
    for (int idx : edges) queried[(size_t)idx] = 1;
}

static string receive_control_from(int sender) {
    while (true) {
        string rep = ask_line("< " + to_string(sender));
        if (rep == "- -" || rep.empty()) continue;
        size_t sp = rep.find(' ');
        if (sp == string::npos) continue;
        int actual = atoi(rep.substr(0, sp).c_str());
        if (actual == sender) return rep.substr(sp + 1);
    }
}

static string broadcast_control(string body, int A, int ID) {
    for (int width = 1; width < A; width <<= 1) {
        if (ID < width) {
            int child = ID + width;
            if (child < A) (void)ask_line("> " + to_string(child) + " " + body);
        } else if (ID < 2 * width) {
            body = receive_control_from(ID - width);
        }
    }
    return body;
}

struct ComponentInfo {
    vector<unsigned char> seen;
    int count = 0;
    int r1 = 0, r2 = -1, c1 = 0, c2 = -1;
    bool has_frontier = false;
    int fr1 = 0, fr2 = -1, fc1 = 0, fc2 = -1;
};

static void include_box(int r, int c, int &r1, int &r2, int &c1, int &c2) {
    if (r2 < r1) {
        r1 = r2 = r;
        c1 = c2 = c;
    } else {
        r1 = min(r1, r);
        r2 = max(r2, r);
        c1 = min(c1, c);
        c2 = max(c2, c);
    }
}

static void each_room_edge(int r, int c, int m,
                           const function<void(int,int,int)> &fn) {
    if (r > 0) fn(r - 1, c, idx_v(r - 1, c, m));
    if (c > 0) fn(r, c - 1, idx_h(r, c - 1, m));
    if (r + 1 < m) fn(r + 1, c, idx_v(r, c, m));
    if (c + 1 < m) fn(r, c + 1, idx_h(r, c, m));
}

static ComponentInfo component_from(int root, int m,
                                    const vector<unsigned char> &edge_open,
                                    const vector<unsigned char> &queried) {
    int V = m * m;
    ComponentInfo info;
    info.seen.assign(V, 0);
    queue<int> q;
    info.seen[(size_t)root] = 1;
    q.push(root);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        int r = u / m, c = u % m;
        ++info.count;
        include_box(r, c, info.r1, info.r2, info.c1, info.c2);
        each_room_edge(r, c, m, [&](int nr, int nc, int eidx) {
            int v = nr * m + nc;
            if (edge_open[(size_t)eidx] && !info.seen[(size_t)v]) {
                info.seen[(size_t)v] = 1;
                q.push(v);
            }
        });
    }
    for (int u = 0; u < V; ++u) {
        if (!info.seen[(size_t)u]) continue;
        int r = u / m, c = u % m;
        each_room_edge(r, c, m, [&](int nr, int nc, int eidx) {
            if (!queried[(size_t)eidx]) {
                info.has_frontier = true;
                include_box(nr, nc, info.fr1, info.fr2, info.fc1, info.fc2);
            }
        });
    }
    return info;
}

static Rect expanded_frontier_rect(const ComponentInfo &x, int pad, int m) {
    int r1 = x.has_frontier ? x.fr1 : x.r1;
    int r2 = x.has_frontier ? x.fr2 : x.r2;
    int c1 = x.has_frontier ? x.fc1 : x.c1;
    int c2 = x.has_frontier ? x.fc2 : x.c2;
    return {max(0, r1 - pad), min(m - 1, r2 + pad),
            max(0, c1 - pad), min(m - 1, c2 + pad)};
}

static PhaseSpec diagonal_spec(int hi) {
    return {'D', hi, {0, -1, 0, -1}, {0, -1, 0, -1}};
}

static PhaseSpec final_spec() {
    return {'F', 0, {0, -1, 0, -1}, {0, -1, 0, -1}};
}

static PhaseSpec choose_adaptive_next(int m, int A, int phase_no, int current_hi,
                                      const vector<unsigned char> &edge_open,
                                      const vector<unsigned char> &queried) {
    int remaining = 0;
    for (unsigned char x : queried) remaining += !x;
    if (remaining == 0) return final_spec();

    int max_frontier_phases = (A <= 4 ? 5 : 4);
    if (phase_no >= max_frontier_phases) return final_spec();

    int step = max(8, (m + 8) / 9);
    int next_hi = min(m - 1, current_hi + step);
    if (next_hi <= current_hi && remaining > 0) return final_spec();

    ComponentInfo s = component_from(0, m, edge_open, queried);
    ComponentInfo t = component_from(m * m - 1, m, edge_open, queried);

    // A full diagonal pulse prevents the two local boxes from overfitting to a
    // branch that is not on the final s-t path.
    if (phase_no % 3 == 2 || !s.has_frontier || !t.has_frontier) {
        return diagonal_spec(next_hi);
    }

    int pad = max(8, m / 18) + phase_no * max(3, m / 80);
    PhaseSpec out;
    out.type = 'R';
    out.hi = next_hi;
    out.a = expanded_frontier_rect(s, pad, m);
    out.b = expanded_frontier_rect(t, pad, m);
    return out;
}

static bool should_use_adaptive(int N, int A) {
    return N >= 300 && (A <= 4 || (N >= 360 && 12 <= A && A <= 14));
}

static int run_adaptive_solver(int N, int A, int ID, int MAX_MSG_LEN) {
    int m = (N + 1) / 2;
    int E = edge_count(m);
    int bits_per_msg = max_bits_per_message(MAX_MSG_LEN);
    vector<unsigned char> queried(E, 0);
    vector<unsigned char> edge_open;
    if (ID == 0) edge_open.assign(E, 0);

    int current_hi = min(m - 1, max(2, (25 * m + 99) / 100));
    PhaseSpec spec = diagonal_spec(current_hi);
    int phase_no = 0;

    while (true) {
        vector<int> edges = build_phase_edges(m, spec, queried);
        bool last = (spec.type == 'F');
        vector<unsigned char> bits = query_edge_list(edges, m, A, ID);
        vector<unsigned char> agg = binary_reduce_phase(std::move(bits), (int)edges.size(),
                                                        A, ID, bits_per_msg, last);
        mark_queried(edges, queried);
        if (ID == 0) {
            store_aggregate_edges(edges, A, agg, edge_open);
            string ans = solve_from_edges(N, edge_open);
            if (!ans.empty() || last) {
                claim_answer(ans);
                return 0;
            }

            PhaseSpec next = choose_adaptive_next(m, A, phase_no + 1, current_hi,
                                                  edge_open, queried);
            vector<int> next_edges = build_phase_edges(m, next, queried);
            if (next.type != 'F' && next_edges.empty()) {
                next = final_spec();
            }
            if (next.type == 'D' || next.type == 'R') current_hi = max(current_hi, next.hi);
            spec = next;
        }

        string body = broadcast_control(ID == 0 ? encode_phase_spec(spec) : string(), A, ID);
        if (ID != 0) spec = parse_phase_spec(body);
        ++phase_no;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, A, ID, MAX_MSG_LEN;
    if (!(cin >> N >> A >> ID >> MAX_MSG_LEN)) return 0;
    string rest;
    getline(cin, rest);

    if (N == 1) {
        if (ID == 0) cout << "!" << '\n' << flush;
        else cout << "halt" << '\n' << flush;
        return 0;
    }

    if (should_use_adaptive(N, A)) {
        return run_adaptive_solver(N, A, ID, MAX_MSG_LEN);
    }

    int m = (N + 1) / 2;
    int E = edge_count(m);
    vector<int> bands = choose_bands(m, N, A);
    vector<int> counts;
    vector<int> order = build_edge_order(m, bands, counts);
    int phases = (int)counts.size();
    int bits_per_msg = max_bits_per_message(MAX_MSG_LEN);

    vector<unsigned char> edge_open;
    if (ID == 0) edge_open.assign(E, 0);

    int start = 0;
    for (int ph = 0; ph < phases; ++ph) {
        int count = counts[ph];
        vector<unsigned char> bits = query_phase(start, count, order, m, A, ID);
        bool last = (ph + 1 == phases);
        vector<unsigned char> agg = binary_reduce_phase(std::move(bits), count, A, ID,
                                                        bits_per_msg, last);
        if (ID == 0) {
            store_aggregate_phase(start, count, A, order, agg, edge_open);
            string ans = solve_from_edges(N, edge_open);
            if (!ans.empty() || last) {
                claim_answer(ans);
                return 0;
            }
        }
        start += count;
    }

    if (ID == 0) claim_answer(solve_from_edges(N, edge_open));
    else cout << "halt\n" << flush;
    return 0;
}
