*I cannot find any guide on this on Codeforces.* Codeforces blog if you prefer it: [Codeforces: Debug interactive problem more effectively on Codeforces](https://codeforces.com/blog/entry/142553) Interactive problems are probably the bane of your existence on Codeforces, because they don't appear very often, they can fail on sample testcase and you wouldn't even know, debugging is also hard, among other things. Thus, I will present an easy way (to the best of my knowledge, it is the easiest), to test, debug and probably minimize the number of bugs generated while implementing interactive problems too. ## 1. How to write better code in general. #### Problem statement: *Given $N$ ($N \leq 10^{18}$). Jury has hidden an integer point $(x, y)$ on the 2D plane. It is guaranteed that $0 \leq x, y \leq N$. You have to somehow guess where the point is. You can ask the following question:* *- **`? i j`**: You will ask the point $(i, j)$, and jury will give you the Manhattan distance between the hidden point and the point that you asked.* *When you are done asking, you should answer by **`! i j`**, which means that you think the hidden point coordinate is $(i, j)$.* *Task: Find out the hidden point in the least number of query possible.* <details> <summary>Example interaction:</summary> **`Jury`**: **69** **`You`**: **? 17 17** **`Jury`**: **69** **`You`**: **! 0 69** **`Jury`**: **Correct, here is your money boss.** Note that this isn’t the actual strategy, and the optimal number of queries might not be 1. </details> <details> <summary>Solution:</summary> It is obvious that you cannot find the hidden point in 1 query. What about 2? Turns out, you can. Just ask **`? 0 0`** and **`? N 0`**. Let's call the answer to these queries $u$ and $v$. We have this system of equations: $$ \begin{cases} x + y = u \\ (N - x) + y = v \end{cases} $$ $$ \Rightarrow \begin{cases} y = \frac{u + v - N}{2} \\ x = \frac{u - v + N}{2} \end{cases} $$ </details> Ok, very easy problem, very cool. Here, Let's look at how lil Timmy - our punching bag - a very young and gullible competitive programmer, will implement the solution. <details> <summary>lil Timmy's code:</summary> ```cpp= void solve(){ ll n; cin >> n; cout << "? " << 0 << " " << 0 << "\n"; cout.flush(); ll u; cin >> u; cout << "? " << n << " " << 0 << "\n"; cout.flush(); int v; cin >> v; ll y = (u + v - n) / 2, x = (u - v + n) / 2; cout << "! " << x << " " << y << "\n"; cout.flush(); } ``` </details> He submitted the solution after only testing it on the sample input (which is just how a normal human test interactive problems), and got a WA on test 2 faster than he could blink. What gives? Turns out, he used `int` on line 6, which led to his demise, as the jury output can be up to $2*10^{18}$, and `int` can only store numbers up to $2*10^{9}$, leading to overflow. And this is the problem with how people normally write interactive code. They write input and output directly inside of the code. While you could do fine with it, there is some obvious problems going on: 1. The code looks really ugly. 2. Humans error. Sometimes, your finger slips and you write the interaction wrong, and suddenly you have to scratch your head for tens of minutes, possibly hours looking for that one pesky mistake. 3. What if you read the interaction instruction wrong, and have to modify everything again? This simply isn't good code. 4. It is also very unreadable. While this won't really matter in a 2 hours Codeforces round, it could hinder debugging in longer contests or team contests, and you will also have a hard time reading your own code when revisiting it after months. And this is why you should just put everything inside of functions. <details> <summary>Fixed lil Timmy's code:</summary> ```cpp= ll ask(ll i, ll j){ cout << "? " << i << " " << j << "\n"; cout.flush(); ll ans; cin >> ans; return ans; } void answer(ll i, ll j){ cout << "! " << i << " " << j << "\n"; cout.flush(); } void solve(){ ll n; cin >> n; ll u = ask(0, 0), v = ask(n, 0); ll y = (u + v - n) / 2, x = (u - v + n) / 2; answer(x, y); } ``` </details> By putting every important interactions inside a function, we ensure that every operations behaves the same, which helps avoiding goofy bugs such as using `int` instead of `long long` and can focus on getting the logic correctly instead. This will also make our code much more readable. Sure, it might seem finicky on this beginner problem, but the benefits becomes evident on problems that requires a lot more implementation and logic, such as [2106G2 - Baudelaire (hard).](https://codeforces.com/contest/2106/problem/G2) Additionally, this setup will naturally leads to my way of debugging interactive code, which I shamelessly copied from how OI contests handle interactive problems. ## 2. How to debug interactive problems. It's easy, just make a `.h` library file and write the stress tester there. There is really nothing much to it. Here is an example of how I might write the stress tester for the above problem. <details> <summary>Library file: findpoint.h</summary> ```cpp= #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); ll rand_range(ll l, ll r){return l + (ull) rng() % (r - l + 1);} pair<ll, ll> hidden_point; ll ask(ll i, ll j){ return abs(hidden_point.first - i) + abs(hidden_point.second - j); } void answer(ll i, ll j){ if (make_pair(i, j) != hidden_point) assert(false); } void solve(ll n); int main(void){ ios::sync_with_stdio(0);cin.tie(0); cout.tie(0); const int T = 1000; for(int t = 1; t <= T; ++t){ ll n = rand_range(0, 1e18); hidden_point = make_pair(rand_range(0, n), rand_range(0, n)); solve(n); cout << "Test case number " << t << " ran correctly!" << "\n"; cout.flush(); } return 0; } ``` </details> <details> <summary>Code file: findpoint.cpp</summary> ```cpp= #include "findpoint.h" #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; // ll ask(ll i, ll j){ // cout << "? " << i << " " << j << "\n"; // cout.flush(); // ll ans; cin >> ans; // return ans; // } // void answer(ll i, ll j){ // cout << "! " << i << " " << j << "\n"; // cout.flush(); // } void solve(ll n){ ll u = ask(0, 0), v = ask(n, 0); ll y = (u + v - n) / 2, x = (u - v + n) / 2; answer(x, y); } // int main(void){ // ios::sync_with_stdio(0);cin.tie(0); cout.tie(0); // ll n; cin >> n; // solve(n); // return 0; // } ``` </details> Explaination: I commented out the `main` function and the two interaction functions `answer` and `ask` in the main code file. Then in the library file, I rewrite the two interaction functions and the main function to handle the stress testing. Then just press compile and hey, it ran 1000 tests correctly, let's delete `#include "findpoint.h"` and uncomment the `main`, `ask` and `answer` function, which takes literally 3 key strokes - 1.8 seconds in freedom units, and you are done. Additional notes: - If you don't know what `.h` files are, and what I just did means, either ask ChatGPT or look up C++ docs. Come on, figuring out how to use `.h` files can't possibly be that hard. - You shouldn't have a single `cin` or anything equivalent in the main `solve` function to make it easier to stress test (run the code a lot of times, with different inputs). In my code, I read `n` and pass it into the function. The principle should be the same if the input is an array, a graph or a tree. Try not to use `cin` and instead pass everything by parameters in the function. - Of course, this won't have any use if implementing the grader is harder, more tedious, or both, than implementing the solution itself. These problems are few and far between on Codeforces however. - Yes, strategy matters. Even if most problems only takes from 5-20 minutes to set up the grader, 20 minutes is 20 minutes, and sometimes it is just not worth it. - You can write the grader directly inside the main code instead of a separate `.h` file, and indeed me from my early day do it too. However, I realized that it would make the code really messy and also interfere with the main logic. It’s cleaner to separate what you don’t intend to submit. - You could also do the `#ifdef LOCAL` shenanigans, but from my experience it takes like 2 seconds to comment and uncomment all of these, so no, I don't like that. You can do it if you want though.