希望把所有的题目的分数做个排序orz
ultmaster edited 6 年,11 月前
大家好。
我们增加了两个新功能。
第一个是所有提交现在已经支持对提交详情的查看。除了部分比赛,在错误提交达到一定次数之后,会显示 Need some help?
的提示,你可以选择支付一些 EMB 来获取关于题目 Debug 的帮助。之前是可以下载数据点,我发现大家已经用得非常 6 了。但部分大数据点全部下载下来根本不可能 Debug,而且对于数据点较多的题目全部下载下来要付出较多的 EMB。为了更好地帮助调试,从现在起的所有提交都可以拿到摘要。
包括输入信息、输出信息和比较程序 (checker) 的评价(哪里错了)。
虽然下载数据功能从即日起已经正式关闭,但是不用担心,你之前购买的所有测试点仍然可以在你的账单记录中找到,可以重复下载。
我们上线了一个新的默认比较程序 (default checker),将在比较输出和答案是过滤行末文末空格,并大大优化了输入输出效率。
优化的结果是这个 checker 变得非常复杂和易碎。现将其源代码直接在本 OJ 上开放,如果认为此 checker 存在漏洞的,请携带提交程序拨打报警电话。我们将尽快解决。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define BUFFER_SIZE 100000
#define WA_EXIT_CODE 1
#define FAIL_EXIT_CODE 3
FILE *ouf, *ans, *ret;
inline bool isLineEnding(char c) {
return c == '\r' || c == '\n';
}
inline bool isValidChar(char c) {
return c && !isspace(c);
}
inline bool isCompressChar(char c) {
return c && !isLineEnding(c);
}
class IO {
private:
FILE* file;
char ch, buf[BUFFER_SIZE], *p1, *p2;
public:
int lineCount;
explicit IO(FILE* f): file(f), ch(0), p1(buf), p2(buf), lineCount(1) {
memset(buf, 0, sizeof buf);
}
inline int nextchar(char &r) {
if (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, BUFFER_SIZE, file), p1 == p2)) return 0;
r = *p1++; if (r == '\n') lineCount++; return 1;
}
inline string compress() {
char *lptr = p1, *rptr = p1;
string ans; int i;
for (i = 0; i < 16; ++i) {
if (--lptr != buf - 1 && isCompressChar(*lptr))
ans += *lptr;
else break;
}
if (i == 16) ans += "...";
reverse(ans.begin(), ans.end());
for (i = 0; i < 15; ++i) {
if (rptr != p2 && isCompressChar(*rptr))
ans += *rptr++;
else break;
}
if (i == 15) ans += "...";
return ans;
}
};
void quit(int result) {
fclose(ouf); fclose(ans); fclose(ret);
exit(result);
}
void registerSpj(int argc, char* argv[]) {
if (argc < 4 || argc > 6) {
cout << "Program must be run with the following arguments: "
<< "<input-file> <output-file> <answer-file> [<report-file>]"
<< endl;
exit(FAIL_EXIT_CODE);
} else if (argc == 4) {
ret = stdout;
} if (argc == 5) {
ret = fopen(argv[4], "w");
if (ret == nullptr)
exit(FAIL_EXIT_CODE);
}
ouf = fopen(argv[2], "r");
if (ouf == nullptr) exit(FAIL_EXIT_CODE);
ans = fopen(argv[3], "r");
if (ans == nullptr) exit(FAIL_EXIT_CODE);
}
int main(int argc, char * argv[]) {
registerSpj(argc, argv);
IO outio(ouf), ansio(ans);
char a, b;
int ans_ok, ouf_ok;
while (true) {
ans_ok = ansio.nextchar(a);
ouf_ok = outio.nextchar(b);
if (ans_ok && ouf_ok) {
if (a == b) {
// not eof and equal (ok)
continue;
} else if (a == '\n') {
// ans is at eol but ouf is not
do {
if (isValidChar(b)) {
fprintf(ret, "wrong answer: unexpected character at the end of line %d\n", outio.lineCount);
quit(WA_EXIT_CODE);
}
} while (outio.nextchar(b) && b != '\n');
} else if (b == '\n') {
// ouf is at eol but ans if not
do {
if (isValidChar(a)) {
fprintf(ret, "wrong answer: character missing at the end of line %d\n", outio.lineCount - 1);
quit(WA_EXIT_CODE);
}
} while (ansio.nextchar(a) && a != '\n');
} else {
// wrong answer
fprintf(ret, "wrong answer: line %d differ - expected: '%s', found: '%s'\n", outio.lineCount,
ansio.compress().c_str(), outio.compress().c_str());
quit(WA_EXIT_CODE);
}
} else {
if (!ans_ok && !ouf_ok) {
// both encountered eof
break;
} else if (!ans_ok) {
// ouf is still not eof
do {
if (isValidChar(b)) {
fprintf(ret, "wrong answer: unexpected output at eof\n");
quit(WA_EXIT_CODE);
}
} while (outio.nextchar(b));
} else {
// ans is still not eof but ouf is eof now
do {
if (isValidChar(a)) {
fprintf(ret, "wrong answer: output missing at eof\n");
quit(WA_EXIT_CODE);
}
} while (ansio.nextchar(a));
}
}
}
fprintf(ret, "ok\n");
return 0;
}
最后感谢大家对 EOJ 的支持!
因为你前面就错了后面的根本就不跑了啊(微笑