Hamza Hassanain
Repovive Interactive Problems Guide (Contestants & Setters)
December 26, 2025 • 11 min read • 1 views
We are excited to announce support for Interactive Problems on Repovive! Unlike traditional problems where you read all input at once, interactive problems require your solution to "talk" to the judge in real-time. Think of it as a conversation where each side reacts to the other's messages.
How It Works: The "Conversation"
In a standard problem, the judge pipes a file into your program. In an interactive problem, the judge runs a second program called an Interactor alongside your solution.
The data flow looks like this:
- The Judge reads the hidden test case file (
.in) and feeds it to the Interactor (viastdin). - The Interactor processes the secret and sends a hint to your Solution (via
tout). - Your Solution reads the hint, processes it, and sends a response (via
stdout). - The Interactor reads your response (via
tin) and decides whether to continue the game or end it with a verdict.
For Contestants: How to Solve
Solving an interactive problem is similar to a normal problem, but with one critical requirement: You must flush your output.
The "Idleness Limit" Trap
Most programming languages buffer output to save time. In an interactive problem, if your guess stays in the buffer, the Interactor never receives it. The Interactor waits for you, you wait for the Interactor, and the result is a Time Limit Exceeded (specifically an Idleness Limit).
For our case on Repovive, Idlenss Limit Exceeded Is treated as a Wrong Answer
The Solution:
- C++: Use
std::endl(which flushes) instead of\n. Or callstd::cout.flush(). - Python: Use
print(..., flush=True). - Java: Use
System.out.println()followed bySystem.out.flush().
Sample Solution (C++)
C++
#include <iostream>
#include <string>
using namespace std;
int main() {
int low, high;
// 1. Read the initial range from the Interactor
if (!(cin >> low >> high)) return 0;
while (low <= high) {
int mid = low + (high - low) / 2;
// 2. Send your guess and FLUSH
cout << mid << endl;
// 3. Read the response
string response;
cin >> response;
if (response == "correct") break;
if (response == "higher") low = mid + 1;
else high = mid - 1;
}
return 0;
}
For Problem Setters: Creating the Interactor
To set an interactive problem, you need to write a C++ program using our internal library repovive.h.
The Interface
You do not need to manage pipes or processes. Simply implement the interact() function, and whatever you do, never please, just never put a main function inside the interactor.cpp, the file you upload, **Must NEVER have a main function, **
cin: Reads from the secret test case file (.in).tout: Sends data to the user’sstdin.tin: Reads data from the user’sstdout.cerr: Use this for logging. It will be visible in the interaction logs in the editor page, so please make them meaningful to help our users!
Interactor Template
C++
#include "repovive.h"
bool interact() {
// 1. Read secret data from the judge's .in file
int min_val, max_val, target;
if (!(cin >> min_val >> max_val >> target)) {
cerr << "Setter: Error reading .in file" << endl;
return WRONG_ANSWER;
}
// 2. Send initial data to the user
tout << min_val << " " << max_val << endl;
int max_attempts = 50;
for (int i = 0; i < max_attempts; ++i) {
int guess;
// 3. Read guess from user (tin handles timeouts automatically)
if (!(tin >> guess)) {
cerr << "Verdict: User solution crashed or timed out." << endl;
return WRONG_ANSWER;
}
if (guess == target) {
tout << "correct" << endl;
return ACCEPTED;
}
tout << (guess < target ? "higher" : "lower") << endl;
}
return WRONG_ANSWER; // Exceeded attempts
}
Under the Hood: The Driver Logic
For those interested in the systems side, Repovive's judge uses a custom driver dirver.cpp to manage the sandbox. It leverages:
- Unix Pipes: Redirecting file descriptors between two concurrent processes.
poll()** & Custom Streambufs**: OurTimeoutStreambufensures that if a user's code hangs, the Interactor can detect the lack of data and fail gracefully rather than hanging the entire judge.rlimit: Enforcing strict CPU and Memory limits on the user's sandbox without affecting the Interactor's performance.
Technical Note: On Repovive,
toutis set toios::unitbuf, meaning it flushes automatically. You don't need to manually flushtout, but your users must flush theirstdout.
Best Practices for Setters
- Be Explicit: Clearly state the maximum number of queries allowed in the problem description.
- Validate Input: Always check if
tinfails. If the user sends a string instead of an integer, your interactor should returnWRONG_ANSWERimmediately. - Efficiency: Your interactor logic should be fast ($O(1)$ or $O(\log N)$ per query) because it shares the total execution time limit with the user.
- Consistency: Ensure that the strings you output to
toutexactly match the strings the user is expected to read.