#include #include #include using namespace std; class Number{ public: int n[4]; Number(){}; }; bool operator<(const Number& a, const Number& b){ return ((a.n[0] < b.n[0]) ||((a.n[0] == b.n[0]) && (a.n[1] < b.n[1])) ||((a.n[0] == b.n[0]) && (a.n[1] == b.n[1]) && (a.n[2] < b.n[2])) ||((a.n[0] == b.n[0]) && (a.n[1] == b.n[1]) && (a.n[2] == b.n[2]) && (a.n[3] < b.n[3]))); }; class Q_A{ public: Number num; int hit, blow; }; int hit(const Number& a, const Number& b){ int result = 0; for (int i = 0; i < 4; i++){ if (a.n[i] == b.n[i]) result++; } return result; } int blow(const Number& a, const Number& b){ int result = 0; for (int i = 0; i < 4; i++){ for (int j = 0; j < 4; j++){ if (i == j) continue; else if (a.n[i] == b.n[j]) result++; } } return result; } set gen(){ set result; for (int i = 0; i < 10; i++){ for (int j = 0; j < 10; j++){ for (int k = 0; k < 10; k++){ for (int l = 0; l < 10; l++){ if ((i == j) || (i == k) || (i == l) || (j == k) || (j == l) || (k == l)) continue; else{ Number temp; temp.n[0] = i; temp.n[1] = j; temp.n[2] = k; temp.n[3] = l; result.insert(temp); } } } } } return result; } void remove(set& s, vector& l){ for (int i = 0; i < (int)l.size(); i++){ for (set::iterator iter = s.begin(); iter != s.end();){ int h = hit(*iter, l[i].num); int b = blow(*iter, l[i].num); if ((h != l[i].hit) || (b != l[i].blow)) s.erase(iter++); else ++iter; } } } int main(){ int n; while(cin >> n){ if (n == 0) break; else{ vector l; for (int i = 0; i < n; i++){ Q_A temp; for (int j = 0; j < 4; j++){ char t; cin >> t; temp.num.n[j] = t - '0'; } cin >> temp.hit >> temp.blow; l.push_back(temp); } set s = gen(); remove(s, l); if (s.size() == 1){ const Number& num = *(s.begin()); for (int i = 0; i < 4; i++){ cout << num.n[i]; } cout << endl; }else if (s.size() > 25){ cout << "????" << endl; }else{ set critical = gen(); bool find_flag = false; for (set::iterator iter_c = critical.begin(); iter_c != critical.end(); iter_c++){ bool critical_flag = true; set > hits_and_blows; for (set::iterator iter_s = s.begin(); iter_s != s.end(); iter_s++){ pair hb(hit(*iter_c, *iter_s), blow(*iter_c, *iter_s)); if (hits_and_blows.find(hb) == hits_and_blows.end()){ hits_and_blows.insert(hb); }else{ critical_flag = false; break; } } if (critical_flag){ for (int i = 0; i < 4; i++){ cout << iter_c->n[i]; } cout << endl; find_flag = true; break; } } if (!find_flag) cout << "????" << endl; } } } return 0; }