/** * コミュニケーション問題 ファイル経由通信ハックテスト * * ファイル経由で相手の手札を不正に取得し、正解を出す。 * AC → セキュリティホール! * WA → ファイル通信は正しくブロックされている */ #include #include #include #include #include #include #include #include #include using namespace std; void try_write(const char* path, const string& data) { FILE* f = fopen(path, "w"); if (f) { fprintf(f, "%s", data.c_str()); fclose(f); fprintf(stderr, "[INFO] write ok: %s\n", path); } else { fprintf(stderr, "[INFO] write fail: %s\n", path); } } bool try_read(const char* path, string& out) { FILE* f = fopen(path, "r"); if (!f) return false; char buf[4096]; if (fgets(buf, sizeof(buf), f)) { out = buf; fclose(f); return true; } fclose(f); return false; } int main() { int id, N, M; scanf("%d %d %d", &id, &N, &M); vector hand(N); map my_count; for (int i = 0; i < N; i++) { scanf("%d", &hand[i]); my_count[hand[i]]++; } // 自分の手札を文字列化 string hand_str; for (int i = 0; i < N; i++) { if (i > 0) hand_str += " "; hand_str += to_string(hand[i]); } // 複数パスでファイル書き込みを試みる const char* bases[] = { "/tmp/hack", "/dev/shm/hack", "/var/tmp/hack", "/home/judge/hack", "/home/judge1/hack", }; for (auto base : bases) { char path[256]; snprintf(path, sizeof(path), "%s_%d", base, id); try_write(path, hand_str); } // 相手が書くのを待つ usleep(500000); // 相手の手札を読み取り int other_id = 3 - id; vector opp_hand; map opp_count; bool hacked = false; for (auto base : bases) { char path[256]; snprintf(path, sizeof(path), "%s_%d", base, other_id); string data; if (try_read(path, data)) { istringstream iss(data); int v; opp_hand.clear(); opp_count.clear(); while (iss >> v) { opp_hand.push_back(v); opp_count[v]++; } if ((int)opp_hand.size() == N) { hacked = true; fprintf(stderr, "[HACK] Read opponent hand from %s_%d\n", base, other_id); break; } } } // 全値のCOUNTを集める(質問は必要) map total; int asked = 0; char cmd[16]; while (scanf("%s", cmd) == 1) { if (strcmp(cmd, "END") == 0) { int q; scanf("%d", &q); break; } if (strcmp(cmd, "TURN") == 0) { if (asked < M) { asked++; printf("ASK %d\n", asked); fflush(stdout); } else { // GUESS if (hacked) { // ファイルから相手の手札を知っているので正解可能 vector guess; for (int v = 1; v <= M; v++) { int t = total.count(v) ? total[v] : 0; int c = t - my_count[v] - opp_count[v]; for (int j = 0; j < c; j++) guess.push_back(v); } sort(guess.begin(), guess.end()); printf("GUESS"); for (int v : guess) printf(" %d", v); printf("\n"); } else { // ハック失敗 → 当てずっぽう printf("GUESS"); for (int i = 0; i < N; i++) printf(" 1"); printf("\n"); } fflush(stdout); } } else if (strcmp(cmd, "WAIT") == 0) { // nothing } else if (strcmp(cmd, "COUNT") == 0) { int x, k; scanf("%d %d", &x, &k); total[x] = k; } else if (strcmp(cmd, "GUESSED") == 0) { int g, ok; scanf("%d %d", &g, &ok); } } return 0; }