I cannot find any guide on this on Codeforces, which made me tweak out.
HackMD blog if you prefer it: HackMD: Debug interactive problem more effectively on Codeforces
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.
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.
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:
- The code looks really ugly.
- 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.
- What if you read the interaction instruction wrong, and have to modify everything again? This simply isn't good code.
- 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.
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).
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.
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
.hfiles are, and what I just did means, either ask ChatGPT or look up C++ docs. Come on, figuring out how to use.hfiles can't possibly be that hard. - You shouldn't have a single
cinor anything equivalent in the mainsolvefunction to make it easier to stress test (run the code a lot of times, with different inputs). In my code, I readnand 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 usecinand 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
.hfile, 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 LOCALshenanigans, 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.
















