用Cena评测答案提交类题目的另类方法

    这几天组织了几次省选模拟赛,遇到了答案提交类的题目和交互式的题目。我一直使用Cena进行评测,现在希望把这两种类型的题目方便地加入Cena的评测结果中。交互式的题目使用Cena评测非常简单,只需要在库函数运行时输出一个以得分情况为内容的文件作为选手输出即可(http://www.matrix67.com/blog/article.asp?id=179)。但答案提交类的题目却遇到了麻烦,因为Cena肯定不允许程序访问外部文件(因此不能另写程序读入提交的答案并作为选手输出文件输出),而每个选手提交的答案文件所在位置又不确定(不知道文件夹名),不能把这些文件加入Cena的评测中。后来,我想到了这样一个解决方案。我可以用程序生成一个程序来生成选手输出文件(真他妈的绕口)。

    假设测试点共10个,所有的输入文件名为name.?.in,输出文件名为name.?.out,其中?取1到10中的数。那么下列程序可以生成一个printer.pas作为选手程序。以下程序将选手提交的答案写入pas源代码“printer.pas”中,它可以根据输入文件恰当地进行输出操作。“printer”将被设置为该题的源程序文件名。
    评测时所用的输入文件只有一个整数,标识这是第几个测试点。程序的输出(即选手提交的答案)可以和标准输出比较或另写Checker评分。

program print;
const
   fname='name';
var
   i:integer;
   st:string;

procedure init;
begin
   writeln('program printer;');
   writeln('var n:integer;');
   writeln;
   writeln('begin');
   writeln('   assign(input,'+#39+fname+'.in'+#39+');');
   writeln('   reset(input);');
   writeln('   readln(n);');
   writeln('   close(input);');
   writeln('   assign(output,'+#39+fname+'.out'+#39+');');
   writeln('   rewrite(output);');
   writeln;
end;

begin
   assign(output,'printer.pas');
   rewrite(output);
   init;
   for i:=1 to 10 do
   begin
      str(i,st);
      {$i-}
      assign(input,'name.'+st+'.out');
      reset(input);
      {$i+}
      if ioresult<>0 then continue;
      writeln('   if n=',i,' then begin');
      repeat
         readln(st);
         writeln('      writeln(',#39,st,#39,');');
      until eof;
      writeln('   end;');
      writeln;
   end;
   writeln('   close(output);');
   writeln('end.');
   close(output);
end.

    采取一些工具软件可以在不同的选手文件夹下批处理运行该程序。

    过几天我可能又要思考如何评测循环赛类型的题目了。

做人要厚道
转贴请注明出处

3 条评论

发表评论

77  +    =  82