By PrinceOfPersia, history, 9 years ago, In English

Interactive problems are problems in which solution talks to the judge. For example, 100553G - Gomoku. We don't see interactive problems much in ACM-ICPC style problems. Most of them are Olympiad style(IOI and CEOI). Unfortunately using interactive in Codeforces contests is not allowed, but you can see some of them in Gym. Also Polygon handles such problems(there's a checkbox Interactive in general info of the problem). When we don't wanna handle the judge manually, we should use a code named interactor to talk to code instead of a person. With testlib.h, we can write interactors as simple as checkers and validators.

In an interactive problem, you may use also a checker. To connect this programs together(generator, validator, solution, checker and interactor), you can use teslib input streams. An input stream, is a structure that reads data from a specific file using some pre-implemented methods. Input streams you can use with testlib.h:

  1. inf: It's the input generated by generator or manually (In polygon, manual tests and output of generators, based on how the input file of the current testcase was generated).
  2. ouf: It's the output produced by the solution you're working on.
  3. ans: Output produced by your correct solution.

Also, there's an input/output stream for interactive tasks named tout. It's a log file, you can write some information to it with the interactor and later, check the information written in it with the checker (and determine the verdict). For writing in it, you can use style of C++ cout, like tout << n << endl;. In the checker, you can read that information from ouf.

Methods you can use for input streams: Validator doc

In interactor, you read the information about the current testcase from inf, write what needs to be given to the solution you're checking and the correct solution using stdout (online), read the output produces by the solution you're checking using ouf (online), read the output produces by your correct solution using ans (online) and write log to tout if you want.

If at anytime, some with methods of input streams used in interactor goes wrong(fails), verdict will be Wrong Answer.

Also, you can determine the verdict in interactor. There are much useful methods in teslib you can use in interactors for assert-like checking, ensuring and determining the verdict. You can find them in checker docs (methods like quitf and ensuref).

You can also see possible verdicts in checker docs.

If verdict determined by interactor's ok, then it will be ensured by the checker (which uses tout/ouf) if there's any.

How to use interactor program ?

Simple:

Windows:

interactor.exe <Input_File> <Output_File> [<Answer_File> [<Result_File> [-appes]]],
Reads test from inf (mapped to args[1]), writes result to tout (mapped to argv[2],
can be judged by checker later), reads program output from ouf (mapped to stdin),
writes output to program via stdout (use cout, printf, etc).

Linux:

./interactor.out <Input_File> <Output_File> [<Answer_File> [<Result_File> [-appes]]],
Reads test from inf (mapped to args[1]), writes result to tout (mapped to argv[2],
can be judged by checker later), reads program output from ouf (mapped to stdin),
writes output to program via stdout (use cout, printf, etc).

Sample Interactive Problem

I(judge) choose an integer in the interval [1, 109] and you should write a code to guess it. You can ask me at most 50 questions. In each question, you tell me a number in the interval [1, 109], and I tell you:

  • 1 if it is equal to answer(the chosen number), and your program should stop asking after that.
  • 0 if it is smaller than answer.
  • 2 if it is greater than answer.

Sample interactor for this problem:

Note: Like checkers and validators and generator, you should first initialize your interactor with registerInteraction(argc, argv).

Please note that in this problem, we can determine the verdict without using the correct solution and ans because we don't care about it's product. But in some problems, we'll have to compare it with the product of the correct solution using ans.

int main(int argc, char ** argv){
	registerInteraction(argc, argv);
	int n = inf.readInt();	// chosen integer
	cout.flush();	// to make sure output doesn't stuck in some buffer
	int left = 50;
	bool found = false;
	while(left > 0 && !found){
		left --;
		int a = ouf.readInt(1, 1000000000);	// the number you tell me
		if(a < n)
			cout << 0 << endl;
		else if(a > n)
			cout << 2 << endl;
		else
			cout << 1 << endl, found = true;
		cout.flush();
	}
	if(!found)
		quitf(_wa, "couldn't guess the number with 50 questions");
	ouf.readEof();
	quitf(_ok, "guessed the number with %d questions!", 50 - left);

}

Resources: Checkers, validators and my personal experience from reading one of MikeMirzayanov's interactors.

  • Vote: I like it
  • +36
  • Vote: I do not like it

| Write comment?
»
9 years ago, # |
  Vote: I like it -8 Vote: I do not like it

Auto comment: topic has been updated by PrinceOfPersia (previous revision, new revision, compare).

»
9 years ago, # |
  Vote: I like it +15 Vote: I do not like it

I think it is better to point user to articles checkers & validators for methods readXXX, ensure, quit, verdicts, instead of duplicating the content here. That way, when texts needs to be changed, it only needs to be changed in one place.

»
9 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by PrinceOfPersia (previous revision, new revision, compare).

»
9 years ago, # |
Rev. 3   Vote: I like it +3 Vote: I do not like it

I think that you don't need to print N (see example, line 4) to stdout (maybe you need to print it to log file).

UPD: Fixed.

»
9 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by PrinceOfPersia (previous revision, new revision, compare).

»
9 years ago, # |
  Vote: I like it 0 Vote: I do not like it

I don't know much about interactive problems, but are you sure that we are supposed to read n from inf??

I understand that inf is available to the participant as input.

Maybe here n should be read from some other source?

  • »
    »
    9 years ago, # ^ |
    Rev. 2   Vote: I like it 0 Vote: I do not like it

    In interactive problems input file is available for interactor and if you want to make smth available to participant you should print it in interactor

»
9 years ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

Thanks for your helps. I learn and use all except Interactor!

I used your code as interactor but sorry I don't know what I must write as Checker ?

everything I write , polygon says "wrong output format Expected EOF" in invocation and "Interactor returns with verdict OK and exit code 2, while judging model solution" in Preview Test! In Invocation "Output" field is empty for tests!

my model solution (My tests are in [1,1000])

Can anyone help me or share a sample ? thanks

  • »
    »
    9 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Don't set checker!

    • »
      »
      »
      9 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      without checker , Invocation and Preview Tests did not work. I had a small mistake in model solution and I fixed it , but problem was another thing.

      I don't know exactly why but because of this error "wrong output format Expected EOF" , I changed "ouf.readEof();" in the above code to below code and it works :

      if ( !ouf.seekEof() ) 
      {
      	quitf(_wa, "there is extra output!");
      }
      

      Do you know why ?


      Also I realized that same as normal problems we must read whole "ouf" data in checker, otherwise it will say "PE : wrong output format Extra information in the output file".

      So if you use tout in interactor , you must read all of your outputs in checker . I used this code as checker :

      #include "testlib.h"
      
      int main(int argc, char* argv[])
      {
          registerTestlibCmd(argc, argv);
      	
      	while ( !ouf.seekEof() )
      	    ouf.readToken();
      	
      	quitf( _ok , "OK , Correct" );
      	
          return 0;
      }
      
      • checker accepts solution because it trusted to interactor.
      • »
        »
        »
        »
        8 years ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        Possible explanation for your EOF problems: you have to read EOLN first.

»
8 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by Xellos (previous revision, new revision, compare).

»
8 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Please, explain me why I get Presentation error with Extra Info "See file to check exit message" when try to use exactly the given interactor (with include-s etc added, binary file of the interactor is being created) in ejudge 3.5.1+ ?

Or, can somebody give me a full ready-to-work similar interactor for ejudge? Including the interactor itself, serve.cfg content, etc. I_want to check interactively binary search, so binary search interactor is preferable. But I hope that another examples can be useful too to help me to understand what's wrong.

  • »
    »
    8 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    ejudge 3 is incompatible with testlib. It gives 4-th argument with another meaning. Quick-fix is do registerTestlibCmd(3, argv) instead of (argc, argv). Better way is add some kind of ifdef to testlib.

    • »
      »
      »
      8 years ago, # ^ |
      Rev. 2   Vote: I like it 0 Vote: I do not like it

      We also used ejudge 3 with interactive problems on many Moscow school contests and it worked just fine.

      • »
        »
        »
        »
        8 years ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        I got this problem in SIS. On wiki it's said, ejudge had argument 4 equals to pid of participant process. This will cause testlib to print interactor command to file with such name. Probably, exit code in this situation will be correct, so you just get bad comment. Also, problems can depend on checker.

  • »
    »
    8 years ago, # ^ |
    Rev. 4   Vote: I like it 0 Vote: I do not like it

    We in Samara University use ejudge 3.5.1 and interactive problems work fine JUST AS in older versions of ejudge. We don't feel any differences. And without fixes by PavelKunyavskiy.

    Tell me your Polygon account and I'll share interactive problems.

    • »
      »
      »
      8 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      IlyaCk

    • »
      »
      »
      7 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      Mine is Boxer, can u share some interactive problems, please?

»
8 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Could you please provide example of command that I should run? I'm unable to figure out command I need to write(for linux)

»
5 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Is there a limit on how much data an interactor can print to cout?

It seems like printing 10000 characters works in Invocations section but crashes a package build with a meaningless error message: PackageException: Failed on verification of the first test:

»
3 years ago, # |
  Vote: I like it 0 Vote: I do not like it

How can I upload the interactor? Do I have to upload it as checker or validator? I don't see a field to upload interactors.

  • »
    »
    3 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    You should first check "Interactive problem" on the general info tab, after that a new tab appears.

    • »
      »
      »
      2 years ago, # ^ |
        Vote: I like it -10 Vote: I do not like it

      Also, how can I use a specific format for an example test? For example:

      input
      
      2
      5
      
      1 2 4 5
      
      1 3 5
      
      3
      
      1
      
      output
      
      
      ? 1 4
      
      ? 3 5
      
      ! 2
      
      ? 1 1
      
      ! 1
      

      How can I make it looks like this without presenting the whole test? The test is:

      2
      5
      4 2 5 1 3
      3
      1 3 2
      
»
9 months ago, # |
Rev. 5   Vote: I like it 0 Vote: I do not like it

My main solution had verdict IDLENESS_LIMIT_EXCEEDED on test 1 in the first place in interactor where I read data from ouf. Why?

  • »
    »
    9 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Did you forget to flush the output in your solution or interactor?

    Also, it would be much easier to help if you showed the code of your interactor and solution

    • »
      »
      »
      9 months ago, # ^ |
      Rev. 2   Vote: I like it 0 Vote: I do not like it

      Ok, I will send this today

    • »
      »
      »
      9 months ago, # ^ |
      Rev. 10   Vote: I like it 0 Vote: I do not like it

      There were codes in this comment once, but I delete this.....

      • »
        »
        »
        »
        9 months ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        It seems like your main solution is waiting for scanf("%d\n%d %d", g, n, m) but the interactor never outputs those and instead starts waiting for the first question from the solution.

»
2 weeks ago, # |
  Vote: I like it 0 Vote: I do not like it

how write input for like that format.

? 1232 ! 3224

here is my code:

int main(int argc, char ** argv){
	registerInteraction(argc, argv);
	int n = inf.readInt();	// chosen integer
	cout.flush();
	string ch=to_string(n);
	int left = 20;
	bool found = false;
	while(left > 0 && !found){
		left --;
		char ss = ouf.readToken("?|!")[0];
		string cur=ouf.readToken("[0-9][0-9]{3}");
		if(ss=='!'){
		    if(ch==cur){
		        found=true;
		    }
		    break;
		}
		int cnt=0;
		for(int i=0;i<4;i++){
		    if(ch[i]==cur[i]) cnt++;
		}
		cout << cnt << endl;
        fflush(stdout);
	}
	if(!found)
		quitf(_wa, "couldn't guess the number with 20 questions");
	ouf.readEof();
	quitf(_ok, "guessed the number with %d questions!", 20-left);

}