Problem: cf1557_e
Difficulty: medium
Categories: greedy, data structures
Time limit: 1000 ms, memory limit: 256 MB

This is an interactive problem.

ICPC Assiut Community decided to hold a unique chess contest, and you were chosen to control a queen and hunt down the hidden king, while a member of ICPC Assiut Community controls this king.

You compete on an $8\times8$ chessboard, the rows are numerated from top to bottom, and the columns are numerated left to right, and the cell in row $x$ and column $y$ is denoted as $(x, y)$.

In one turn you can move the queen to any of the squares on the same horizontal line, vertical line, or any of the diagonals. For example, if the queen was on square ($4$, $5$), you can move to ($q_1$, $5$), ($4$, $q_1$), ($q_1$, $9-q_1$), or ($q_2$, $q_2+1$) where ($1 \le q_1 \le 8$, $q_1 \ne 4$, $1 \le q_2 \le 7$, $q_2 \ne 4$). Note that the queen cannot stay on its current cell.

 ![](https://espresso.codeforces.com/00b3c485be65888f6a17b2d1f262e897a8ac4c87.png) 

In one turn, the king can move "Right", "Left", "Up", "Down", "Down-Right", "Down-Left", "Up-Left", or "Up-Right" such that he doesn't get out of the board. The king cannot move into a cell that is on the same row, column or diagonal with the queen (including the position of the queen itself). For example, if the king was on square ($4$, $5$), he can move to ($4+k_1$, $5+k_2$) where ($-1 \le k_1,k_2 \le 1$, $(k_1, k_2) \ne (0, 0)$).

 ![](https://espresso.codeforces.com/42bad3cf689c0f3a26299f15417c88e2e4217268.png) 

At the start of the game, you should place the queen at any location on the board, and this is done once per game. After that the king is secretly placed at any cell different from the queen's location. You do not know the position of the king. Then, the king and the queen take turns with the king moving first. The king moves to one of the possible directions ("Right", "Down", "Up-Left", etc.), and you are only given the direction it moves to. After that, you should move your queen by declaring the square to which your queen will move. The game follows like this until you win the game or run out of moves.

You win if the king has no valid moves. You lose if after $130$ moves of the queen the king still has valid moves.

Input

The first line contains a single integer $t$ ($1 \le t \le 60$) — the number of test cases.

Interaction

In each test case, you should print the queen's starting cell immediately. If you placed the queen at the king's cell, you will win immediately.

After that, you may make at most $130$ moves. Each move is made in the format $x$ $y$, where $x$ and $y$ are two integers ($1 \leq x,y \leq 8$) that denote the new row and column of the queen respectively. Your move should be a valid queen move.

After the initial queen placement and after each move you will receive a string $s$ that represents the direction of the king's move. It will be one of the following: "Right", "Left", "Up", "Down", "Down-Right", "Down-Left", "Up-Left", "Up-Right", or "Done" if you win the game. You should consider "Done" as the end of each test case.

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.

If at any point you make an invalid query or try to make more than $130$ queries for each test case, the game will terminate immediately and you will receive a Wrong Answer verdict.

Example

Input

```
1
Left
Right
Done
```

Output

```
7 5
7 6
7 7
```

Note

In the example, the hidden king was at $(8, 8)$ at the start. The game follows like this:

 ![](https://espresso.codeforces.com/580233bdef883a90b0c5d1071f28abef110cb745.png)  ![](https://espresso.codeforces.com/1e77e8e2850c2a493eb8a12f3ed2e974876dc255.png)

Non-adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << "\n";
        tout << "query_limit=" << query_limit << "\n";
        tout.flush();
    } catch (...) {
        
    }
}

static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

struct Pos {
    int x = 0;
    int y = 0;
};

static bool in_board(const Pos& p) {
    return 1 <= p.x && p.x <= 8 && 1 <= p.y && p.y <= 8;
}

static bool attacked_by_queen(const Pos& cell, const Pos& queen) {
    return cell.x == queen.x || cell.y == queen.y || (cell.x + cell.y) == (queen.x + queen.y) ||
           (cell.x - cell.y) == (queen.x - queen.y);
}

struct KingMove {
    int dx;
    int dy;
    const char* name;
};

static const KingMove KMOVES[8] = {
    {0, 1, "Right"},
    {0, -1, "Left"},
    {1, 0, "Down"},
    {-1, 0, "Up"},
    {1, 1, "Down-Right"},
    {1, -1, "Down-Left"},
    {-1, -1, "Up-Left"},
    {-1, 1, "Up-Right"},
};

static vector<pair<Pos, const char*>> legal_king_moves(const Pos& king, const Pos& queen) {
    vector<pair<Pos, const char*>> mv;
    for (const auto& m : KMOVES) {
        Pos nxt{king.x + m.dx, king.y + m.dy};
        if (!in_board(nxt)) continue;
        if (attacked_by_queen(nxt, queen)) continue;
        mv.push_back({nxt, m.name});
    }
    return mv;
}

static int mobility(const Pos& king, const Pos& queen) {
    return (int)legal_king_moves(king, queen).size();
}

static pair<Pos, const char*> choose_king_move(const Pos& king, const Pos& queen) {
    auto moves = legal_king_moves(king, queen);
    if (moves.empty()) return {{0, 0}, "Done"};
    int best = -1;
    pair<Pos, const char*> best_move = moves[0];
    for (const auto& cand : moves) {
        int score = mobility(cand.first, queen);
        if (score > best) {
            best = score;
            best_move = cand;
        }
    }
    return best_move;
}

static bool valid_queen_move(const Pos& from, const Pos& to) {
    if (!in_board(to)) return false;
    if (from.x == to.x && from.y == to.y) return false;
    if (from.x == to.x) return true;
    if (from.y == to.y) return true;
    if ((from.x + from.y) == (to.x + to.y)) return true;
    if ((from.x - from.y) == (to.x - to.y)) return true;
    return false;
}

int main(int argc, char* argv[]) {
    registerInteraction(argc, argv);
    atexit(log_metrics);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    const int t = inf.readInt(1, 60, "t");
    vector<Pos> kings(t);
    for (int tc = 0; tc < t; tc++) {
        kings[tc].x = inf.readInt(1, 8, "king_x");
        kings[tc].y = inf.readInt(1, 8, "king_y");
    }
    if (!inf.seekEof()) finish(_fail, "Unexpected extra tokens in hidden input");

    query_limit = 130LL * t;
    const long long hard_cap = max(200000LL, 10LL * max(1LL, query_limit));

    log_metrics(); 

    cout << t << "\n";
    cout.flush();

    for (int tc = 0; tc < t; tc++) {
        Pos king = kings[tc];
        Pos queen;
        if (!(cin >> queen.x >> queen.y)) finish(_pe, "Unexpected EOF reading initial queen position");
        if (!in_board(queen)) finish(_wa, "Initial queen position out of board");

        long long moves_used = 0; 

        
        if (queen.x == king.x && queen.y == king.y) {
            cout << "Done\n";
            cout.flush();
            continue;
        }

        while (true) {
            
            auto mv = choose_king_move(king, queen);
            if (strcmp(mv.second, "Done") == 0) {
                cout << "Done\n";
                cout.flush();
                break;
            }

            king = mv.first;
            cout << mv.second << "\n";
            cout.flush();

            
            Pos nxt;
            if (!(cin >> nxt.x >> nxt.y)) finish(_pe, "Unexpected EOF reading queen move");
            moves_used++;
            queries++;
            if (queries > hard_cap) finish(_pe, "Hard cap exceeded (possible infinite loop)");
            if (moves_used > 130) finish(_wa, "Exceeded per-test move limit (130)");

            if (!valid_queen_move(queen, nxt)) finish(_wa, "Invalid queen move");
            queen = nxt;

            
            if (queen.x == king.x && queen.y == king.y) {
                cout << "Done\n";
                cout.flush();
                break;
            }
        }
    }

    finish(_ok, "OK");
}


Adaptive interactor (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static long long queries = 0;
static long long query_limit = 0;

static void log_metrics() {
    try {
        tout << "queries=" << queries << "\n";
        tout << "query_limit=" << query_limit << "\n";
        tout.flush();
    } catch (...) {
        
    }
}

static void finish(TResult verdict, const string& msg) {
    log_metrics();
    quitf(verdict, "%s", msg.c_str());
}

struct Pos {
    int x = 0;
    int y = 0;
};

static bool in_board(const Pos& p) {
    return 1 <= p.x && p.x <= 8 && 1 <= p.y && p.y <= 8;
}

static bool attacked_by_queen(const Pos& cell, const Pos& queen) {
    return cell.x == queen.x || cell.y == queen.y || (cell.x + cell.y) == (queen.x + queen.y) ||
           (cell.x - cell.y) == (queen.x - queen.y);
}

struct KingMove {
    int dx;
    int dy;
    const char* name;
};

static const KingMove KMOVES[8] = {
    {0, 1, "Right"},
    {0, -1, "Left"},
    {1, 0, "Down"},
    {-1, 0, "Up"},
    {1, 1, "Down-Right"},
    {1, -1, "Down-Left"},
    {-1, -1, "Up-Left"},
    {-1, 1, "Up-Right"},
};

static vector<pair<Pos, const char*>> legal_king_moves(const Pos& king, const Pos& queen) {
    vector<pair<Pos, const char*>> mv;
    for (const auto& m : KMOVES) {
        Pos nxt{king.x + m.dx, king.y + m.dy};
        if (!in_board(nxt)) continue;
        if (attacked_by_queen(nxt, queen)) continue;
        mv.push_back({nxt, m.name});
    }
    return mv;
}

static int mobility(const Pos& king, const Pos& queen) {
    return (int)legal_king_moves(king, queen).size();
}

static pair<Pos, const char*> choose_king_move(const Pos& king, const Pos& queen) {
    auto moves = legal_king_moves(king, queen);
    if (moves.empty()) return {{0, 0}, "Done"};
    int best = -1;
    pair<Pos, const char*> best_move = moves[0];
    for (const auto& cand : moves) {
        int score = mobility(cand.first, queen);
        if (score > best) {
            best = score;
            best_move = cand;
        }
    }
    return best_move;
}

static bool valid_queen_move(const Pos& from, const Pos& to) {
    if (!in_board(to)) return false;
    if (from.x == to.x && from.y == to.y) return false;
    if (from.x == to.x) return true;
    if (from.y == to.y) return true;
    if ((from.x + from.y) == (to.x + to.y)) return true;
    if ((from.x - from.y) == (to.x - to.y)) return true;
    return false;
}

static Pos choose_initial_king(const vector<Pos>& candidates, const Pos& queen) {
    Pos best = candidates.empty() ? Pos{1, 1} : candidates[0];
    int best_score = -1;
    for (const auto& p : candidates) {
        if (!in_board(p)) continue;
        
        int score = mobility(p, queen);
        if (score > best_score) {
            best_score = score;
            best = p;
        }
    }
    return best;
}

int main(int argc, char* argv[]) {
    registerInteraction(argc, argv);
    atexit(log_metrics);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    const int t = inf.readInt(1, 60, "t");
    vector<vector<Pos>> king_sets(t);
    for (int tc = 0; tc < t; tc++) {
        const int m = inf.readInt(1, 64, "m");
        king_sets[tc].reserve(m);
        for (int i = 0; i < m; i++) {
            Pos p;
            p.x = inf.readInt(1, 8, "king_x");
            p.y = inf.readInt(1, 8, "king_y");
            king_sets[tc].push_back(p);
        }
    }
    if (!inf.seekEof()) finish(_fail, "Unexpected extra tokens in adaptive hidden input");

    query_limit = 130LL * t;
    const long long hard_cap = max(200000LL, 10LL * max(1LL, query_limit));

    log_metrics(); 

    cout << t << "\n";
    cout.flush();

    for (int tc = 0; tc < t; tc++) {
        Pos queen;
        if (!(cin >> queen.x >> queen.y)) finish(_pe, "Unexpected EOF reading initial queen position");
        if (!in_board(queen)) finish(_wa, "Initial queen position out of board");

        Pos king = choose_initial_king(king_sets[tc], queen);
        if (!in_board(king)) finish(_fail, "Internal: chosen king out of board");

        long long moves_used = 0;

        if (queen.x == king.x && queen.y == king.y) {
            cout << "Done\n";
            cout.flush();
            continue;
        }

        while (true) {
            auto mv = choose_king_move(king, queen);
            if (strcmp(mv.second, "Done") == 0) {
                cout << "Done\n";
                cout.flush();
                break;
            }
            king = mv.first;
            cout << mv.second << "\n";
            cout.flush();

            Pos nxt;
            if (!(cin >> nxt.x >> nxt.y)) finish(_pe, "Unexpected EOF reading queen move");
            moves_used++;
            queries++;
            if (queries > hard_cap) finish(_pe, "Hard cap exceeded (possible infinite loop)");
            if (moves_used > 130) finish(_wa, "Exceeded per-test move limit (130)");
            if (!valid_queen_move(queen, nxt)) finish(_wa, "Invalid queen move");
            queen = nxt;

            if (queen.x == king.x && queen.y == king.y) {
                cout << "Done\n";
                cout.flush();
                break;
            }
        }
    }

    finish(_ok, "OK");
}



Test generator (C++):
#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

static vector<pair<int,int>> allCells() {
    vector<pair<int,int>> v;
    for (int x = 1; x <= 8; x++)
        for (int y = 1; y <= 8; y++)
            v.push_back({x, y});
    return v;
}

static vector<pair<int,int>> edgeCells() {
    vector<pair<int,int>> v;
    for (int x = 1; x <= 8; x++) {
        for (int y = 1; y <= 8; y++) {
            if (x == 1 || x == 8 || y == 1 || y == 8) v.push_back({x, y});
        }
    }
    return v;
}

int main(int argc, char** argv) {
    registerGen(argc, argv, 1);

    string mode = opt<string>("mode", "non");
    long long seedVal = 1;
    if (argc >= 2) {
        try { seedVal = stoll(string(argv[1])); }
        catch (...) { seedVal = 1; }
    }

    if (mode == "non") {
        int kx = opt<int>("kx", -1);
        int ky = opt<int>("ky", -1);

        if (kx == -1 || ky == -1) {
            if (seedVal == 1) {
                kx = 1; ky = 1;              
            } else if (seedVal == 2) {
                kx = 1; ky = 4;              
            } else if (seedVal == 3) {
                kx = 4; ky = 4;              
            } else {
                
                vector<pair<int,int>> pool;
                for (int x = 2; x <= 7; x++)
                    for (int y = 2; y <= 7; y++)
                        pool.push_back({x, y});
                for (int rep = 0; rep < 6; rep++) {
                    pool.push_back({4,4});
                    pool.push_back({4,5});
                    pool.push_back({5,4});
                    pool.push_back({5,5});
                }
                int idx = rnd.next(0, (int)pool.size() - 1);
                kx = pool[idx].first;
                ky = pool[idx].second;

                
                if (rnd.next(1, 10) == 1) {
                    vector<pair<int,int>> tricky = {{3,5},{5,3},{6,4},{4,6},{3,4},{4,3},{6,5},{5,6}};
                    auto p = tricky[rnd.next(0, (int)tricky.size() - 1)];
                    kx = p.first; ky = p.second;
                }
            }
        }

        if (!(1 <= kx && kx <= 8 && 1 <= ky && ky <= 8)) {
            
            kx = 4; ky = 5;
        }

        cout << 1 << "\n";
        cout << kx << " " << ky << "\n";
        return 0;
    }

    if (mode == "adp") {
        
        vector<pair<int,int>> cells;
        if (seedVal == 1) {
            
            cells = {{1,1},{1,8},{8,1},{8,8}};
        } else if (seedVal == 2) {
            
            cells = edgeCells();
        } else {
            
            cells = allCells();
        }

        
        if (seedVal > 3) {
            
            if (rnd.next(1, 5) == 1) {
                int removeCnt = rnd.next(1, 6);
                vector<int> idx(cells.size());
                iota(idx.begin(), idx.end(), 0);
                for (int i = 0; i < removeCnt && (int)cells.size() > 10; i++) {
                    int j = rnd.next(0, (int)idx.size() - 1);
                    int rem = idx[j];
                    idx.erase(idx.begin() + j);
                    
                }
                
                set<pair<int,int>> forbid;
                int want = removeCnt;
                while (want-- > 0 && (int)forbid.size() < removeCnt) {
                    auto p = cells[rnd.next(0, (int)cells.size() - 1)];
                    forbid.insert(p);
                }
                vector<pair<int,int>> kept;
                kept.reserve(cells.size());
                for (auto &p : cells) if (!forbid.count(p)) kept.push_back(p);
                if (!kept.empty()) cells.swap(kept);
            }
        }

        cout << 1 << "\n";
        cout << (int)cells.size() << "\n";
        for (auto &p : cells) {
            cout << p.first << " " << p.second << "\n";
        }
        return 0;
    }

    
    cout << 1 << "\n";
    cout << 4 << " " << 5 << "\n";
    return 0;
}