#include<cstdio>
#include<vector>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

bool is_valid(const char *a,const char *b,int hit,int blow){
	rep(i,4) rep(j,4) if(a[i]==b[j]) {
		if(i==j) hit--;
		else     blow--;
	}
	return hit==0 && blow==0;
}

int main(){
	vector<int> cand0; // どの桁の数字も異なるような 4 桁の数
	rep(i,10000){
		char s[5]; sprintf(s,"%04d",i);
		if(!(s[0]==s[1] || s[0]==s[2] || s[0]==s[3] || s[1]==s[2] || s[1]==s[3] || s[2]==s[3]))
			cand0.push_back(i);
	}

	for(int n;scanf("%d",&n),n;){
		vector<int> in(n),hit(n),blow(n);
		rep(i,n) scanf("%d%d%d",&in[i],&hit[i],&blow[i]);

		// 入力された質問に矛盾しない数全体
		vector<int> cand;
		rep(j,cand0.size()){
			char s[5]; sprintf(s,"%04d",cand0[j]);
			bool ok=true;
			rep(i,n){
				char t[5]; sprintf(t,"%04d",in[i]);
				if(!is_valid(s,t,hit[i],blow[i])){ ok=false; break; }
			}
			if(ok) cand.push_back(cand0[j]);
		}

		if(cand.size()==1){
			printf("%04d\n",cand[0]);
			continue;
		}

		if(cand.size()>16){
			puts("????");
			continue;
		}

		int ans=-1;
		rep(i,cand0.size()){
			char s[5]; sprintf(s,"%04d",cand0[i]); // 最後の 1 回に発言するべき数

			bool ok=true;
			vector<int> reply(cand.size());
			rep(j,cand.size()){
				char t[5]; sprintf(t,"%04d",cand[j]);
				int hit=0,blow=0;
				rep(k,4) rep(l,4) if(s[k]==t[l]) {
					if(k==l) hit++;
					else     blow++;
				}
				reply[j]=hit*10+blow;
				rep(k,j) if(reply[k]==reply[j]) { ok=false; break; }
			}

			if(ok){ // 真の解がどれであったとしても特定できるとき
				if(ans==-1){ ans=cand0[i]; break; }
			}
		}

		if(ans!=-1) printf("%04d\n",ans);
		else        puts("????");
	}

	return 0;
}