Problem: cf1100_d
Difficulty: easy
Categories: greedy, data structures, game
Time limit: 2000 ms, memory limit: 256 MB

This is an interactive task.

Dasha and NN like playing chess. While playing a match they decided that normal chess isn't interesting enough for them, so they invented a game described below.

There are $666$ black rooks and $1$ white king on the chess board of size $999 \times 999$. The white king wins if he gets checked by rook, or, in other words, if he moves onto the square which shares either a row or column with a black rook.

The sides take turns, starting with white. NN plays as a white king and on each of his turns he moves a king to one of the squares that are adjacent to his current position either by side or diagonally, or, formally, if the king was on the square $(x, y)$, it can move to the square $(nx, ny)$ if and only $\max (|nx - x|, |ny - y|) = 1$, $1 \leq nx, ny \leq 999$. NN is also forbidden from moving onto the squares occupied with black rooks, however, he can move onto the same row or column as a black rook.

Dasha, however, neglects playing by the chess rules, and instead of moving rooks normally she moves one of her rooks on any space devoid of other chess pieces. It is also possible that the rook would move onto the same square it was before and the position wouldn't change. However, she can't move the rook on the same row or column with the king.

Each player makes $2000$ turns, if the white king wasn't checked by a black rook during those turns, black wins.

NN doesn't like losing, but thinks the task is too difficult for him, so he asks you to write a program that will always win playing for the white king. Note that Dasha can see your king and play depending on its position.

Input

In the beginning your program will receive $667$ lines from input. Each line contains two integers $x$ and $y$ ($1 \leq x, y \leq 999$) — the piece's coordinates. The first line contains the coordinates of the king and the next $666$ contain the coordinates of the rooks. The first coordinate denotes the number of the row where the piece is located, the second denotes the column. It is guaranteed that initially the king isn't in check and that all pieces occupy different squares.

Output

After getting king checked, you program should terminate immediately without printing anything extra.

Interaction

To make a move with the king, output two integers $x$ and $y$ ($1 \leq x, y \leq 999$) — the square to which the king would be moved. The king cannot move onto the square already occupied by a rook. It is guaranteed that the king would always have a valid move.

After each of your turns read the rook's turn in the following format: a single line containing three integers $k$, $x$ and $y$ ($1 \leq k \leq 666$, $1 \leq x_i, y_i \leq 999$) — the number of the rook that would move and the square it would move to. It is guaranteed that the rook wouldn't move to a square already occupied by another chess piece, but it can move onto the square where it was before the turn so that its position wouldn't change. It is guaranteed that the move does not put your king into a check. If your king got in check, all three integers would be equal to $-1$ and in that case your program should terminate immediately.

After printing your turn 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.

Answer "0 0 0" instead of a correct answer means that you made an invalid query. Exit immediately after receiving "0 0 0" and you will see Wrong answer verdict. Otherwise you can get an arbitrary verdict because your solution will continue to read from a closed stream.

Example

Input

```
999 999  
1 1  
1 2  
2 1  
2 2  
1 3  
2 3  
<...>  
26 13  
26 14  
26 15  
26 16  
  
1 700 800  
  
2 1 2  
  
<...>  
  
-1 -1 -1
```

Output

```
999 998  
  
999 997  
  
<...>  
  
999 26
```

Note

The example is trimmed. The full initial positions of the rooks in the first test are available at [link omitted]. It is not guaranteed that they will behave as in the example.

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());
}

static bool readToken(string& s) {
    s.clear();
    if (!(cin >> s)) return false;
    return true;
}

static bool parseLL(const string& s, long long& v) {
    if (s.empty()) return false;
    int i = 0;
    if (s[0] == '-') i = 1;
    if (i == (int)s.size()) return false;
    for (; i < (int)s.size(); i++) {
        if (s[i] < '0' || s[i] > '9') return false;
    }
    try {
        size_t pos = 0;
        long long x = stoll(s, &pos, 10);
        if (pos != s.size()) return false;
        v = x;
        return true;
    } catch (...) {
        return false;
    }
}

static bool readLL(long long& v) {
    string s;
    if (!readToken(s)) return false;
    return parseLL(s, v);
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    const int B = 999;
    const int R = 666;

    int kx = inf.readInt(1, B, "king_x");
    int ky = inf.readInt(1, B, "king_y");
    vector<pair<int,int>> rooks;
    rooks.reserve(R);
    for (int i = 0; i < R; i++) {
        int x = inf.readInt(1, B, "rook_x");
        int y = inf.readInt(1, B, "rook_y");
        rooks.push_back({x, y});
    }

    query_limit = 2000;
    log_metrics(); 

    cout << kx << " " << ky << "\n";
    for (auto [x, y] : rooks) cout << x << " " << y << "\n";
    cout.flush();

    vector<vector<char>> occ(B + 1, vector<char>(B + 1, 0));
    occ[kx][ky] = 1;
    for (auto [x, y] : rooks) occ[x][y] = 1;

    auto inBounds = [&](int x, int y) -> bool { return 1 <= x && x <= B && 1 <= y && y <= B; };

    auto inCheck = [&]() -> bool {
        for (auto [x, y] : rooks) {
            if (x == kx || y == ky) return true;
        }
        return false;
    };

    auto sendInvalid = [&]() {
        cout << "0 0 0\n";
        cout.flush();
    };

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

    for (int turn = 1; turn <= (int)query_limit; turn++) {
        long long nxLL, nyLL;
        if (!readLL(nxLL) || !readLL(nyLL)) {
            finish(_pe, "unexpected EOF / malformed king move");
        }
        queries++;
        if (queries > hard_cap) {
            finish(_pe, "hard cap exceeded");
        }

        if (!inBounds((int)nxLL, (int)nyLL)) {
            sendInvalid();
            finish(_wa, "king move out of bounds");
        }

        int nx = (int)nxLL, ny = (int)nyLL;
        int dx = abs(nx - kx), dy = abs(ny - ky);
        if (max(dx, dy) != 1) {
            sendInvalid();
            finish(_wa, "king move not adjacent");
        }
        if (occ[nx][ny]) {
            sendInvalid();
            finish(_wa, "king moved onto occupied square");
        }

        occ[kx][ky] = 0;
        kx = nx; ky = ny;
        occ[kx][ky] = 1;

        if (inCheck()) {
            cout << "-1 -1 -1\n";
            cout.flush();
            finish(_ok, "king is checked");
        }

        
        int rk = 1;
        int rx = rooks[0].first;
        int ry = rooks[0].second;

        if (rx == kx || ry == ky) {
            
            finish(_fail, "internal error: rook shares row/col with king while not in check");
        }

        cout << rk << " " << rx << " " << ry << "\n";
        cout.flush();
    }

    finish(_wa, "king not checked within 2000 turns");
}


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());
}

static inline int idx(int x, int y) { return x * 1000 + y; }

static bool inb(int v, int B) { return 1 <= v && v <= B; }

static bool is_int_token(const string& s) {
    if (s.empty()) return false;
    int i = 0;
    if (s[0] == '-') {
        if (s.size() == 1) return false;
        i = 1;
    }
    for (; i < (int)s.size(); i++) if (s[i] < '0' || s[i] > '9') return false;
    return true;
}

static bool read_ll(long long& out) {
    string tok;
    if (!(cin >> tok)) return false;
    if (!is_int_token(tok)) return false;
    try {
        size_t p = 0;
        long long v = stoll(tok, &p);
        if (p != tok.size()) return false;
        out = v;
        return true;
    } catch (...) {
        return false;
    }
}

struct MoveChoice {
    int k = 1;
    int x = 1;
    int y = 1;
    bool moved = false;
};

static pair<int,int> pick_square_far(int B, int kx, int ky, const vector<int>& board) {
    auto ok_strict = [&](int x, int y) -> bool {
        if (!inb(x, B) || !inb(y, B)) return false;
        if (x == kx || y == ky) return false;
        if (abs(x - kx) < 2) return false;
        if (abs(y - ky) < 2) return false;
        if (board[idx(x, y)] != -1) return false;
        return true;
    };
    auto ok_relaxed = [&](int x, int y) -> bool {
        if (!inb(x, B) || !inb(y, B)) return false;
        if (x == kx || y == ky) return false;
        if (board[idx(x, y)] != -1) return false;
        return true;
    };

    auto farX = [&](int d, bool primary) -> int {
        bool kingLow = (kx <= B / 2);
        if (!primary) kingLow = !kingLow;
        return kingLow ? (B - d) : (1 + d);
    };
    auto farY = [&](int d, bool primary) -> int {
        bool kingLow = (ky <= B / 2);
        if (!primary) kingLow = !kingLow;
        return kingLow ? (B - d) : (1 + d);
    };

    for (int pass = 0; pass < 2; pass++) {
        for (int d = 0; d <= B - 1; d++) {
            int x1 = farX(d, true), x2 = farX(d, false);
            int y1 = farY(d, true), y2 = farY(d, false);
            pair<int,int> cand[4] = {{x1,y1},{x1,y2},{x2,y1},{x2,y2}};
            for (auto [x, y] : cand) {
                if (pass == 0 ? ok_strict(x, y) : ok_relaxed(x, y)) return {x, y};
            }
        }
    }

    
    return { (kx == 1 ? 2 : 1), (ky == 1 ? 2 : 1) };
}

static MoveChoice choose_dasha_move(
    int B,
    int kx, int ky,
    vector<pair<int,int>>& rooks,               
    vector<int>& board,                         
    vector<int>& rowCount,
    vector<int>& colCount
) {
    vector<int> badRows, badCols;
    if (kx - 1 >= 1) badRows.push_back(kx - 1);
    if (kx + 1 <= B) badRows.push_back(kx + 1);
    if (ky - 1 >= 1) badCols.push_back(ky - 1);
    if (ky + 1 <= B) badCols.push_back(ky + 1);

    auto in_list = [&](int v, const vector<int>& lst) -> bool {
        for (int x : lst) if (x == v) return true;
        return false;
    };

    int bestIdx = 0; 
    long long bestScore = LLONG_MIN;

    for (int i = 0; i < (int)rooks.size(); i++) {
        int rx = rooks[i].first, ry = rooks[i].second;
        int rd = abs(rx - kx);
        int cd = abs(ry - ky);

        long long score = 0;
        bool immediate = in_list(rx, badRows) || in_list(ry, badCols);
        bool near2 = (abs(rx - kx) == 2) || (abs(ry - ky) == 2);

        if (immediate) score += 1000000000LL;
        if (near2) score += 10000000LL;

        if (rd == 1) score += 1000000;
        if (cd == 1) score += 1000000;
        if (rd == 2) score += 10000;
        if (cd == 2) score += 10000;
        if (rd == 3) score += 100;
        if (cd == 3) score += 100;

        
        score = score * 1000 - i;

        if (score > bestScore) {
            bestScore = score;
            bestIdx = i;
        }
    }

    MoveChoice res;
    res.k = bestIdx + 1;

    
    int rx = rooks[bestIdx].first, ry = rooks[bestIdx].second;
    bool shouldMove = (abs(rx - kx) <= 2) || (abs(ry - ky) <= 2);

    if (!shouldMove) {
        res.x = rx;
        res.y = ry;
        res.moved = false;
        return res;
    }

    
    board[idx(rx, ry)] = -1;
    rowCount[rx]--;
    colCount[ry]--;

    auto [nx, ny] = pick_square_far(B, kx, ky, board);

    
    rooks[bestIdx] = {nx, ny};
    board[idx(nx, ny)] = res.k;
    rowCount[nx]++;
    colCount[ny]++;

    res.x = nx;
    res.y = ny;
    res.moved = true;
    return res;
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
    atexit(log_metrics);

    const int B = 999;
    const int R = 666;
    query_limit = 2000;
    const long long hard_cap = max(200000LL, 10LL * query_limit);

    
    log_metrics();

    int kx = inf.readInt(1, B, "king_x");
    int ky = inf.readInt(1, B, "king_y");

    vector<pair<int,int>> rooks;
    rooks.reserve(R);

    vector<int> board(1000 * 1000, -1);
    vector<int> rowCount(B + 1, 0), colCount(B + 1, 0);

    board[idx(kx, ky)] = -2; 

    for (int i = 1; i <= R; i++) {
        int x = inf.readInt(1, B, ("rook_x_" + to_string(i)).c_str());
        int y = inf.readInt(1, B, ("rook_y_" + to_string(i)).c_str());
        if (board[idx(x, y)] != -1) finish(_pe, "invalid hidden input: duplicate piece square");
        if (x == kx || y == ky) finish(_pe, "invalid hidden input: king initially in check");
        rooks.push_back({x, y});
        board[idx(x, y)] = i;
        rowCount[x]++;
        colCount[y]++;
    }

    
    cout << kx << " " << ky << "\n";
    for (int i = 0; i < R; i++) {
        cout << rooks[i].first << " " << rooks[i].second << "\n";
    }
    cout.flush();

    for (int turn = 1; turn <= (int)query_limit; turn++) {
        long long nx_ll, ny_ll;
        if (!read_ll(nx_ll) || !read_ll(ny_ll)) {
            finish(_wa, "unexpected EOF or malformed king move");
        }
        queries++;
        if (queries > hard_cap) finish(_pe, "too many queries");

        if (nx_ll < 1 || nx_ll > B || ny_ll < 1 || ny_ll > B) {
            cout << "0 0 0" << endl;
            finish(_wa, "king move out of bounds");
        }

        int nx = (int)nx_ll, ny = (int)ny_ll;
        int dx = abs(nx - kx), dy = abs(ny - ky);
        if (max(dx, dy) != 1) {
            cout << "0 0 0" << endl;
            finish(_wa, "king move not adjacent");
        }
        if (board[idx(nx, ny)] >= 1) {
            cout << "0 0 0" << endl;
            finish(_wa, "king moved onto a rook square");
        }

        
        board[idx(kx, ky)] = -1;
        kx = nx; ky = ny;
        board[idx(kx, ky)] = -2;

        
        if (rowCount[kx] > 0 || colCount[ky] > 0) {
            cout << "-1 -1 -1" << endl;
            finish(_ok, "king is checked (wins)");
        }

        
        MoveChoice mv = choose_dasha_move(B, kx, ky, rooks, board, rowCount, colCount);

        
        if (!inb(mv.k, R) || !inb(mv.x, B) || !inb(mv.y, B)) finish(_pe, "internal: illegal rook move generated");
        if (mv.x == kx || mv.y == ky) finish(_pe, "internal: rook moved onto king row/col");
        if (board[idx(mv.x, mv.y)] != mv.k) finish(_pe, "internal: rook placement mismatch");
        if (rowCount[kx] != 0 || colCount[ky] != 0) finish(_pe, "internal: king in check after rook move");

        cout << mv.k << " " << mv.x << " " << mv.y << endl;
    }

    finish(_wa, "king was not checked within 2000 turns");
}


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

static int distToSegment(int v, int l, int r) {
    if (v < l) return l - v;
    if (v > r) return v - r;
    return 0;
}

static int pickSegmentStartAvoid(int B, int len, int forbidden, int ref, int extraTries) {
    int maxStart = B - len + 1;
    ensure(maxStart >= 1);

    auto valid = [&](int s) -> bool {
        if (s < 1 || s > maxStart) return false;
        int l = s, r = s + len - 1;
        return !(l <= forbidden && forbidden <= r);
    };

    auto score = [&](int s) -> int {
        int l = s, r = s + len - 1;
        return distToSegment(ref, l, r);
    };

    vector<int> cand;
    cand.push_back(1);
    cand.push_back(maxStart);
    cand.push_back(max(1, min(maxStart, ref - len / 2)));
    cand.push_back(max(1, min(maxStart, forbidden - len)));
    cand.push_back(max(1, min(maxStart, forbidden + 1)));
    cand.push_back(max(1, min(maxStart, forbidden - len / 2)));

    int bestS = -1, bestScore = -1;
    for (int s : cand) {
        if (!valid(s)) continue;
        int sc = score(s);
        if (sc > bestScore) {
            bestScore = sc;
            bestS = s;
        }
    }

    for (int i = 0; i < extraTries; i++) {
        int s = rnd.next(1, maxStart);
        if (!valid(s)) continue;
        int sc = score(s);
        if (sc > bestScore) {
            bestScore = sc;
            bestS = s;
        }
    }

    if (bestS != -1) return bestS;

    
    for (int s = 1; s <= maxStart; s++) {
        if (valid(s)) return s;
    }
    ensure(false);
    return 1;
}

static vector<pair<int,int>> genBlock(int B, int R, int kx, int ky, int a, int b) {
    ensure(1 <= a && a <= B);
    ensure(1 <= b && b <= B);
    ensure(1 <= kx && kx <= B);
    ensure(1 <= ky && ky <= B);
    ensure(a < B && b < B); 

    int rowStart = pickSegmentStartAvoid(B, a, kx, kx, 40);
    int colStart = pickSegmentStartAvoid(B, b, ky, ky, 40);

    vector<pair<int,int>> rooks;
    rooks.reserve(R);
    for (int i = 0; i < a && (int)rooks.size() < R; i++) {
        int x = rowStart + i;
        ensure(x != kx);
        for (int j = 0; j < b && (int)rooks.size() < R; j++) {
            int y = colStart + j;
            ensure(y != ky);
            rooks.push_back({x, y});
        }
    }
    ensure((int)rooks.size() == R);
    return rooks;
}

static vector<pair<int,int>> genCross(int B, int R, int kx, int ky, int r, int c) {
    ensure(1 <= r && r <= B);
    ensure(1 <= c && c <= B);
    ensure(r != kx);
    ensure(c != ky);

    vector<pair<int,int>> rooks;
    rooks.reserve(R);

    int first = R / 2;
    for (int y = 1; y <= B && (int)rooks.size() < first; y++) {
        if (y == ky) continue;
        rooks.push_back({r, y});
    }
    ensure((int)rooks.size() == first);

    for (int x = 1; x <= B && (int)rooks.size() < R; x++) {
        if (x == kx) continue;
        if (x == r) continue; 
        rooks.push_back({x, c});
    }
    ensure((int)rooks.size() == R);
    return rooks;
}

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

    string mode = opt<string>("mode", "non");
    int B = opt<int>("board", 999);
    int R = opt<int>("rooks", 666);

    ensure(B == 999);
    ensure(R == 666);

    long long seed = 0;
    if (argc >= 2) seed = atoll(argv[1]);

    int kx = 500, ky = 500;
    vector<pair<int,int>> rooks;

    if (seed == 1) {
        kx = 1; ky = 1;
        
        int a = 27, b = 27;
        int rowStart = B - a + 1;
        int colStart = B - b + 1;
        rooks.reserve(R);
        for (int i = 0; i < a && (int)rooks.size() < R; i++) {
            for (int j = 0; j < b && (int)rooks.size() < R; j++) {
                rooks.push_back({rowStart + i, colStart + j});
            }
        }
    } else if (seed == 2) {
        kx = 500; ky = 500;
        
        int r = 1;
        int c = 1;
        if (r == kx) r = B;
        if (c == ky) c = B;
        rooks = genCross(B, R, kx, ky, r, c);
    } else if (seed == 3) {
        kx = B; ky = B;
        
        int a = 27, b = 27;
        int rowStart = 1;
        int colStart = 1;
        rooks.reserve(R);
        for (int i = 0; i < a && (int)rooks.size() < R; i++) {
            for (int j = 0; j < b && (int)rooks.size() < R; j++) {
                rooks.push_back({rowStart + i, colStart + j});
            }
        }
    } else {
        if (mode != "non" && mode != "adp") mode = "non";

        
        int lo = B / 3, hi = 2 * B / 3;
        kx = rnd.next(lo, hi);
        ky = rnd.next(lo, hi);

        if (mode == "non") {
            
            int a = rnd.next(18, 38);
            int b = (R + a - 1) / a;
            if (b < 18) b = 18;
            if (a * b < R) b++;
            if (a >= B) a = B - 1;
            if (b >= B) b = B - 1;
            while (a * b < R) {
                if (b + 1 < B) b++;
                else if (a + 1 < B) a++;
                else break;
            }
            ensure(a * b >= R);
            rooks = genBlock(B, R, kx, ky, a, b);
        } else { 
            
            int r = (kx <= B / 2 ? B : 1);
            int c = (ky <= B / 2 ? B : 1);
            if (r == kx) r = (r == 1 ? B : 1);
            if (c == ky) c = (c == 1 ? B : 1);
            rooks = genCross(B, R, kx, ky, r, c);
        }
    }

    ensure((int)rooks.size() == R);

    
    set<pair<int,int>> used;
    used.insert({kx, ky});
    for (auto [x, y] : rooks) {
        ensure(1 <= x && x <= B);
        ensure(1 <= y && y <= B);
        ensure(x != kx && y != ky);
        ensure(!used.count({x, y}));
        used.insert({x, y});
    }

    cout << kx << " " << ky << "\n";
    for (auto [x, y] : rooks) {
        cout << x << " " << y << "\n";
    }
    return 0;
}