#include #include #include #include "validate.h" const double eps = 1e-6; struct point_t { double x, y; double oriented_area(point_t const &l, point_t const &r) const { double x1 = l.x - x; double y1 = l.y - y; double x2 = r.x - x; double y2 = r.y - y; return x1 * y2 - y1 * x2; } double dist2(point_t const &that) const { double dx = x - that.x; double dy = y - that.y; return dx * dx + dy * dy; } }; struct circle_t : point_t { int r; bool is_inside_me(circle_t const &that) const { if (r < that.r) { return false; } double d2 = dist2(that); double rdiff = (r - that.r + eps) * (r - that.r + eps); return d2 <= rdiff; } }; int main(int argc, char **argv) { init_io(argc, argv); // Read problem input circle_t plug[3], socket[3]; for (unsigned i = 0; i < 3; ++i) { if (!(judge_in >> plug[i].x >> plug[i].y >> plug[i].r)) { judge_error("Cannot read problem input (plug)"); } } for (unsigned i = 0; i < 3; ++i) { if (!(judge_in >> socket[i].x >> socket[i].y >> socket[i].r)) { judge_error("Cannot read problem input (socket)"); } } // Read judge's output (only the first line) std::string expected_response; if (!(judge_ans >> expected_response)) { judge_error("Cannot read the first line of jury output"); } // Read author's output std::string actual_response; if (!(author_out >> actual_response)) { wrong_answer("Cannot read the first line"); } if (actual_response == "NO") { // do nothing more } else if (actual_response == "YES") { // read remaining data and validate it circle_t author_pts[3]; for (unsigned i = 0; i < 3; ++i) { if (!(author_out >> author_pts[i].x >> author_pts[i].y)) { wrong_answer("Could not read point #%d", i + 1); } author_pts[i].r = plug[i].r; } // check the distances for (unsigned i = 0; i < 2; ++i) { for (unsigned j = i + 1; j < 3; ++j) { double plugd = sqrt(plug[i].dist2(plug[j])); double authd = sqrt(author_pts[i].dist2(author_pts[j])); if (std::abs(plugd - authd) > 1e-6) { wrong_answer("Distance between pins %u and %u is wrong (was %.15f, now %.15f)", i + 1, j + 1, plugd, authd); } } } // check the orientation double plug_orient = plug[0].oriented_area(plug[1], plug[2]); double auth_orient = author_pts[0].oriented_area(author_pts[1], author_pts[2]); if (std::abs(plug_orient - auth_orient) > 1e-2) { wrong_answer("Triangle orientation is different (oriented area was %.15f, now %.15f)", plug_orient, auth_orient); } // check whether it plugs if (!socket[0].is_inside_me(author_pts[0])) { wrong_answer("Earths do not match"); } if (!(socket[1].is_inside_me(author_pts[1]) && socket[2].is_inside_me(author_pts[2])) && !(socket[1].is_inside_me(author_pts[2]) && socket[2].is_inside_me(author_pts[1]))) { wrong_answer("Phases do not match (either way)"); } } else { wrong_answer("The first line is neither 'YES' nor 'NO'"); } // Check for more data std::string trash; if (author_out >> trash) { wrong_answer("Extra data at the end of file"); } // Decide what to do for output type mismatches if (actual_response == "YES" && expected_response == "NO") { judge_error("Contestant found an answer, jury did not!"); } if (actual_response == "NO" && expected_response == "YES") { wrong_answer("Contestant did not find an answer"); } // If not failed, accept accept(); }