#include // clang-format off using namespace std; #define debug1(a) { cerr<<#a<<":"<; const int L = 5; const int N = 30; const int D = 10; const int LOCAL = 0; namespace Judge { class Judge { public: vector> local_ans; vector success; vector, vector>> history; void initialize_ans() { if (!LOCAL) return; std::random_device seed_gen; mt19937 engine; engine.seed(seed_gen()); local_ans.clear(); for (int i = 0; i < N; i++) { while (true) { vector ten(10); iota(ten.begin(), ten.end(), 0); shuffle(ten.begin(), ten.end(), engine); vector five(5); for (int k = 0; k < 5; k++) { five[k] = ten[k]; } bool ok = true; for (auto e : local_ans) { if (e == five) ok = false; } if (ok) { local_ans.push_back(five); break; } } } success = vector(N); } vector request(vector q) { for (int k = 0; k < 5; k++) { cout << q[k]; } cout << endl; vector res(N); if (LOCAL) { for (int i = 0; i < N; i++) { if (success[i]) { res[i] = {5, 0}; continue; } int h = 0; int b = 0; for (int k = 0; k < 5; k++) { for (int l = 0; l < 5; l++) { if (q[k] == local_ans[i][l]) { if (k == l) { h++; } else { b++; } } } } res[i] = {h, b}; if (res[i] == pii{5, 0}) { success[i] = 1; } } sort(res.begin(), res.end()); } else { for (int i = 0; i < N; i++) { cin >> res[i].first >> res[i].second; } } history.push_back({q, res}); return res; } }; } // namespace Judge class Solver { public: vector> get_candidate() { auto check = [](string s) { sort(s.begin(), s.end()); for (int i = 1; i < s.size(); i++) { if (s[i - 1] == s[i]) { return false; } } return true; }; vector s; for (int i = 0; i <= 99999; i++) { int v = i; string cur; for (int j = 0; j < 5; j++) { cur.push_back('0' + v % 10); v /= 10; } reverse(cur.begin(), cur.end()); if (check(cur)) { s.push_back(cur); } } vector> res; for (auto &nx : s) { vector q = {nx[0] - '0', nx[1] - '0', nx[2] - '0', nx[3] - '0', nx[4] - '0'}; res.push_back(q); } return res; } void solve() { mt19937 engine; { std::random_device seed_gen; engine.seed(seed_gen()); } auto judge = Judge::Judge(); judge.initialize_ans(); // vector> candidate = get_candidate(); set> checked; int success = 0; tuple> prev = {-1, {-1, -1}, {0, 1, 2, 3, 4}}; while (true) { // debug1(judge.history.size()); vector q; for (int it = 0; it < 10000; it++) { q = get<2>(prev); if (!judge.history.size()) break; auto best_match = get<1>(prev); if (it >= 100) { vector ten(10); iota(ten.begin(), ten.end(), 0); shuffle(ten.begin(), ten.end(), engine); vector five(5); for (int k = 0; k < 5; k++) { five[k] = ten[k]; } q = five; } else if (best_match.first + best_match.second == L) { int si = 0; int sj = 0; while (si == sj) { si = engine() % L; sj = engine() % L; } swap(q[si], q[sj]); } else { int k = engine() % L; int d = engine() % D; q[k] = d; } if (checked.count(q)) continue; set qs; for (auto e : q) qs.insert(e); if (qs.size() != 5) continue; break; } checked.insert(q); auto res = judge.request(q); int now_success = 0; pair best = {-1, {-1, -1}}; for (int i = 0; i < N; i++) { int h, b; tie(h, b) = res[i]; if (h == 5) { now_success++; } else { int f = h * 10 + b * 9; // TODO best = max(best, {f, {h, b}}); } } if (now_success == N) { debug1(judge.history.size()); return; } assert(success <= now_success); if (success < now_success || best.first >= get<0>(prev)) { prev = {best.first, best.second, q}; } success = now_success; } } }; int main() { Solver().solve(); return 0; }