感谢涛巨
记录一下,省的以后忘记了。
/* Utility functions for writing output validators for the Kattis * problem format. * * The primary functions and variables available are the following. * In many cases, the only functions needed are "init_io", * "wrong_answer", and "accept". * * - init_io(argc, argv): * initialization * * - judge_in, judge_ans, author_out: * std::istream objects for judge input file, judge answer * file, and submission output file. * * - accept(): * exit and give Accepted! * * - accept_with_score(double score): * exit with Accepted and give a score (for scoring problems) * * - judge_message(std::string msg, ...): * printf-style function for emitting a judge message (a * message that gets displayed to a privileged user with access * to secret data etc). * * - wrong_answer(std::string msg, ...): * printf-style function for exitting and giving Wrong Answer, * and emitting a judge message (which would typically explain * the cause of the Wrong Answer) * * - judge_error(std::string msg, ...): * printf-style function for exitting and giving Judge Error, * and emitting a judge message (which would typically explain * the cause of the Judge Error) * * - author_message(std::string msg, ...): * printf-style function for emitting an author message (a * message that gets displayed to the author of the * submission). (Use with caution, and be careful not to let * it leak information!) * */ #pragma once #include <sys/stat.h> #include <cassert> #include <cstdarg> #include <cstdlib> #include <iostream> #include <fstream> #include <sstream> typedef void (*feedback_function)(const std::string &, ...); const int EXITCODE_AC = 42; const int EXITCODE_WA = 43; const std::string FILENAME_AUTHOR_MESSAGE = "teammessage.txt"; const std::string FILENAME_JUDGE_MESSAGE = "judgemessage.txt"; const std::string FILENAME_JUDGE_ERROR = "judgeerror.txt"; const std::string FILENAME_SCORE = "score.txt"; #define USAGE "%s: judge_in judge_ans feedback_dir < author_out\n" std::ifstream judge_in, judge_ans; std::istream author_out(std::cin.rdbuf()); char *feedbackdir = NULL; void vreport_feedback(const std::string &category, const std::string &msg, va_list pvar) { std::ostringstream fname; if (feedbackdir) fname << feedbackdir << '/'; fname << category; FILE *f = fopen(fname.str().c_str(), "a"); assert(f); vfprintf(f, msg.c_str(), pvar); fclose(f); } void report_feedback(const std::string &category, const std::string &msg, ...) { va_list pvar; va_start(pvar, msg); vreport_feedback(category, msg, pvar); } void author_message(const std::string &msg, ...) { va_list pvar; va_start(pvar, msg); vreport_feedback(FILENAME_AUTHOR_MESSAGE, msg, pvar); } void judge_message(const std::string &msg, ...) { va_list pvar; va_start(pvar, msg); vreport_feedback(FILENAME_JUDGE_MESSAGE, msg, pvar); } void wrong_answer(const std::string &msg, ...) { va_list pvar; va_start(pvar, msg); vreport_feedback(FILENAME_JUDGE_MESSAGE, msg, pvar); exit(EXITCODE_WA); } void judge_error(const std::string &msg, ...) { va_list pvar; va_start(pvar, msg); vreport_feedback(FILENAME_JUDGE_ERROR, msg, pvar); assert(0); } void accept() { exit(EXITCODE_AC); } void accept_with_score(double scorevalue) { report_feedback(FILENAME_SCORE, "%.9le", scorevalue); exit(EXITCODE_AC); } bool is_directory(const char *path) { struct stat entry; return stat(path, &entry) == 0 && S_ISDIR(entry.st_mode); } void init_io(int argc, char **argv) { if(argc < 4) { fprintf(stderr, USAGE, argv[0]); judge_error("Usage: %s judgein judgeans feedbackdir [opts] < userout", argv[0]); } // Set up feedbackdir first, as that allows us to produce feedback // files for errors in the other parameters. if (!is_directory(argv[3])) { judge_error("%s: %s is not a directory\n", argv[0], argv[3]); } feedbackdir = argv[3]; judge_in.open(argv[1], std::ios_base::in); if (judge_in.fail()) { judge_error("%s: failed to open %s\n", argv[0], argv[1]); } judge_ans.open(argv[2], std::ios_base::in); if (judge_ans.fail()) { judge_error("%s: failed to open %s\n", argv[0], argv[2]); } author_out.rdbuf(std::cin.rdbuf()); } #include <regex> using namespace std; int main(int argc, char **argv) { init_io(argc, argv); int n, m, rounds = 0, no_matches = 0; judge_in >> n >> m; bool played[m][n][m][n]; memset(played, 0, sizeof(played)); regex match_regex("([A-Za-z])([0-9]+)-([A-Za-z])([0-9]+)"); string line; while (getline(author_out, line)) { rounds++; istringstream iss(line); string match; bool pr[m][n]; memset(pr, 0, sizeof(pr)); while (iss >> match) { cout << match << endl; smatch mr; if (!regex_match(match, mr, match_regex)) { wrong_answer("Invalid match format in round %d: %s", rounds, match.c_str()); } char c1 = mr[1].str()[0], c2 = mr[3].str()[0]; int t1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 - 'A') : (c1 - 'a'); int t2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 - 'A') : (c2 - 'a'); int p1 = atoi(mr[2].str().c_str()) - 1, p2 = atoi(mr[4].str().c_str()) - 1; if (t1 < 0 || t2 < 0 || t1 >= m || t2 >= m || p1 < 0 || p2 < 0 || p1 >= n || p2 >= n) { wrong_answer("Invalid player reference in round %d: %s", rounds, match.c_str()); } if (t1 == t2) { wrong_answer("Round %d: %s: Players from same team should not play against each other", rounds, match.c_str()); } if (played[t1][p1][t2][p2]) { wrong_answer("Round %d: %s: Players have already played against each other", rounds, match.c_str()); } if (pr[t1][p1] || pr[t2][p2]) { wrong_answer("Round %d: %s: Players have already played in this round", rounds, match.c_str()); } pr[t1][p1] = true; pr[t2][p2] = true; played[t1][p1][t2][p2] = true; played[t2][p2][t1][p1] = true; no_matches++; } } if (rounds > n * (m-1) + 1) { wrong_answer("Too many rounds! Solution had %d rounds, but only %d allowed.", rounds, n * (m-1) + 1); } if (no_matches != m*n*(m-1)*n/2) { wrong_answer("There are %d matches missing in the schedule!", m*n*(m-1)*n/2 - no_matches); } accept(); }
修改的地方:
#include <sys/stat.h> #include <cassert> #include <cstdarg> #include <cstdlib> #include <iostream> #include <fstream> #include <sstream> typedef void (*feedback_function)(const std::string &, ...); const int EXITCODE_AC =0; const int EXITCODE_WA = 1; const std::string FILENAME_AUTHOR_MESSAGE = "teammessage.txt"; const std::string FILENAME_JUDGE_MESSAGE = "judgemessage.txt"; const std::string FILENAME_JUDGE_ERROR = "judgeerror.txt"; const std::string FILENAME_SCORE = "score.txt"; #define USAGE "%s: judge_in judge_ans feedback_dir < author_out\n" std::ifstream judge_in, judge_ans; std::ifstream author_out; char *feedbackdir = NULL; void vreport_feedback(const std::string &category, const std::string &msg, va_list pvar) { std::ostringstream fname; if (feedbackdir) fname << feedbackdir << '/'; fname << category; FILE *f = fopen(fname.str().c_str(), "a"); assert(f); vfprintf(f, msg.c_str(), pvar); fclose(f); } void report_feedback(const std::string &category, const std::string &msg, ...) { va_list pvar; va_start(pvar, msg); vreport_feedback(category, msg, pvar); } void author_message(const std::string &msg, ...) { va_list pvar; va_start(pvar, msg); vreport_feedback(FILENAME_AUTHOR_MESSAGE, msg, pvar); } void judge_message(const std::string &msg, ...) { va_list pvar; va_start(pvar, msg); vreport_feedback(FILENAME_JUDGE_MESSAGE, msg, pvar); } void wrong_answer(const std::string &msg, ...) { //va_list pvar; //va_start(pvar, msg); //vreport_feedback(FILENAME_JUDGE_MESSAGE, msg, pvar); exit(EXITCODE_WA); } void judge_error(const std::string &msg, ...) { //va_list pvar; // va_start(pvar, msg); // vreport_feedback(FILENAME_JUDGE_ERROR, msg, pvar); assert(0); } void accept() { exit(EXITCODE_AC); } void accept_with_score(double scorevalue) { // report_feedback(FILENAME_SCORE, "%.9le", scorevalue); exit(EXITCODE_AC); } bool is_directory(const char *path) { struct stat entry; return stat(path, &entry) == 0 && S_ISDIR(entry.st_mode); } void init_io(int argc, char **argv) { /* if(argc < 4) { fprintf(stderr, USAGE, argv[0]); judge_error("Usage: %s judgein judgeans feedbackdir [opts] < userout", argv[0]); } if (!is_directory(argv[3])) { judge_error("%s: %s is not a directory\n", argv[0], argv[3]); } feedbackdir = argv[3]; */ judge_in.open(argv[1], std::ios_base::in); if (judge_in.fail()) { judge_error("%s: failed to open %s\n", argv[0], argv[1]); } judge_ans.open(argv[2], std::ios_base::in); if (judge_ans.fail()) { judge_error("%s: failed to open %s\n", argv[0], argv[2]); } author_out.open(argv[3], std::ios_base::in); if (author_out.fail()) { judge_error("%s: failed to open %s\n", argv[0], argv[3]);/// } } #include <regex> using namespace std; int main(int argc, char **argv) { init_io(argc, argv); int n, m, rounds = 0, no_matches = 0; judge_in >> n >> m; bool played[m][n][m][n]; memset(played, 0, sizeof(played)); regex match_regex("([A-Za-z])([0-9]+)-([A-Za-z])([0-9]+)"); string line; while (getline(author_out, line)) { rounds++; istringstream iss(line); string match; bool pr[m][n]; memset(pr, 0, sizeof(pr)); while (iss >> match) { cout << match << endl; smatch mr; if (!regex_match(match, mr, match_regex)) { wrong_answer("Invalid match format in round %d: %s", rounds, match.c_str()); } char c1 = mr[1].str()[0], c2 = mr[3].str()[0]; int t1 = (c1 >= 'A' && c1 <= 'Z') ? (c1 - 'A') : (c1 - 'a'); int t2 = (c2 >= 'A' && c2 <= 'Z') ? (c2 - 'A') : (c2 - 'a'); int p1 = atoi(mr[2].str().c_str()) - 1, p2 = atoi(mr[4].str().c_str()) - 1; if (t1 < 0 || t2 < 0 || t1 >= m || t2 >= m || p1 < 0 || p2 < 0 || p1 >= n || p2 >= n) { wrong_answer("Invalid player reference in round %d: %s", rounds, match.c_str()); } if (t1 == t2) { wrong_answer("Round %d: %s: Players from same team should not play against each other", rounds, match.c_str()); } if (played[t1][p1][t2][p2]) { wrong_answer("Round %d: %s: Players have already played against each other", rounds, match.c_str()); } if (pr[t1][p1] || pr[t2][p2]) { wrong_answer("Round %d: %s: Players have already played in this round", rounds, match.c_str()); } pr[t1][p1] = true; pr[t2][p2] = true; played[t1][p1][t2][p2] = true; played[t2][p2][t1][p1] = true; no_matches++; } } if (rounds > n * (m-1) + 1) { wrong_answer("Too many rounds! Solution had %d rounds, but only %d allowed.", rounds, n * (m-1) + 1); } if (no_matches != m*n*(m-1)*n/2) { wrong_answer("There are %d matches missing in the schedule!", m*n*(m-1)*n/2 - no_matches); } accept(); }