#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <set>
#include <cstring>
#include <sstream>

using namespace std;

int N;
string ss[10001];
int hit[10001];
int blow[10001];
bool isValid[10001];

bool check(string org,string tgt,int hits,int blows){
    int h=0;
    int b=0;
    for(int i=0;i<tgt.size();i++){
        if(tgt[i]==org[i]){
            h++;
        }
        else{
            bool ok=false;
            for(int j=0;j<org.size();j++){
                if(org[j]==tgt[i]){
                    ok=true;
                    break;
                }
            }
            if(ok){
                b++;
            }
        }
    }
    return (hits==h)&&(blows==b);
}
pair<int,int> getPii(string org,string tgt){
    int h=0;
    int b=0;
    for(int i=0;i<tgt.size();i++){
        if(tgt[i]==org[i]){
            h++;
        }
        else{
            bool ok=false;
            for(int j=0;j<org.size();j++){
                if(org[j]==tgt[i]){
                    ok=true;
                    break;
                }
            }
            if(ok){
                b++;
            }
        }
    }
    return make_pair(h,b);
}


int main(){

    while(cin>>N&&N){
        memset(isValid,0,sizeof(isValid));
        for(int i=0;i<N;i++)
            cin>>ss[i]>>hit[i]>>blow[i];
        // ÃÈðvZ
        int cnt=0;
        vector<string> cands;
        for(int i=123;i<10001;i++){
            int a=i;
            set<int> s;
            while(a){
                s.insert(a%10);
                a/=10;
            }
            if(i<1000){
                s.insert(0);
            }
            bool ok=true;
            stringstream sss;
            sss<<i;
            string org=sss.str();
            if(s.size()==4){
                if(org.size()==3)org='0'+org;
                // eÉÂ¢ÄhitÆblowª³µ¢©vZ
                for(int j=0;j<N;j++){
                    ok&=check(org,ss[j],hit[j],blow[j]);
                    if(!ok)break;
                }
            }
            else ok=false;
            isValid[i]=ok;
            if(isValid[i]){
                cnt++;
                cands.push_back(org);
            }
        }
        if(cnt==0)cout<<"????"<<endl;
        else if(cnt==1){
            for(int i=123;i<=10000;i++){
                if(isValid[i]){
                    stringstream sss;
                    sss<<i;
                    string os=sss.str();
                    if(os.size()==3)os='0'+os;
                    cout<<os<<endl;
                    break;
                }
            }
        }
        // ¡óâª éê,ÔÉ²×é
        else{
            bool ok=false;
            for(int i=123;i<10001;i++){
                stringstream sss;
                sss<<i;
                string org=sss.str();
                if(org.size()==3)org='0'+org;
                set<char> sc;
                for(int i=0;i<org.size();i++)sc.insert(org[i]);
                if(sc.size()!=4)continue;

                set<pair<int,int> >  spii;
                // hitÆblowÌð¦é
                int prv=0;
                for(int j=0;j<cands.size();j++){
                    spii.insert(getPii(org,cands[j]));
                    if(spii.size()!=prv+1)break;
                    else prv=spii.size();
                }
                if(spii.size()==cands.size()){
                    cout<<org<<endl;
                    ok=true;
                    break;
                }
            }
            if(!ok)cout<<"????"<<endl;
        }
    }

    return 0;
}

Measured memory_bytes: 0