/*
  AOJ 2084
  Title:Hit & Blow
  @kankichi573
*/
#include <stdio.h>
#define min(x,y) (((x)<(y))?(x):(y))
#define max(x,y) (((x)>(y))?(x):(y))
int N;
int attempt;
int flag[10][10][10][10];

int hit(char trial[],char secret[])
{
  int i,ret=0;

  for(i=0;i<4;i++)
    ret += ((trial[i]==secret[i])?1:0);

  //printf("H:%s %s %d",trial,secret,ret);
  return(ret);
}
int blow(char trial[],char secret[])
{
  int i,j,ret=0;
  
  for(i=0;i<4;i++)
    for(j=0;j<4;j++)
      ret += (((i!=j)&&(trial[i]==secret[j]))?1:0);
  //printf("B:%s %s %d",trial,secret,ret);
  return(ret);
}
void check(char trial[4],int h,int b)
{
  char s[5];
  int h1,b1;
  s[4]='\0';

  for(s[0]='0';s[0]<='9';s[0]++)
    {
        for(s[1]='0';s[1]<='9';s[1]++)
	  {
	    if(s[1]==s[0])
	      continue;
	    for(s[2]='0';s[2]<='9';s[2]++)
	      {
		if(s[2]==s[0]||s[2]==s[1])
		  continue;
		for(s[3]='0';s[3]<='9';s[3]++)
		  {
		    if(s[3]==s[0]||s[3]==s[1]||s[3]==s[2])
		      continue;

		    h1=hit(s,trial);b1=blow(s,trial);
		    if(h1==h && b1==b)
		      {
			//printf("%s %d %d:\n",s,h1,b1);
		        flag[s[0]-'0'][s[1]-'0'][s[2]-'0'][s[3]-'0']++;
		      }
		  }
	      }
	  }
    }
}
void clear()
{
  int i,j,k,l;

  for(i=0;i<10;i++)
    for(j=0;j<10;j++)
      for(k=0;k<10;k++)    
	for(l=0;l<10;l++)
	  flag[i][j][k][l]=0;
}

calc_critical(int n1,int n2)
{
  char s1[5],s2[5],s[5];
  int  h1,h2,b1,b2,ret;

  s[4]=0;
  //printf("cr= %d %d\n",n1,n2);
  sprintf(s1,"%04d",n1);
  sprintf(s2,"%04d",n2);
  
  for(s[0]='0';s[0]<='9';s[0]++)
    {
        for(s[1]='0';s[1]<='9';s[1]++)
	  {
	    if(s[1]==s[0])
	      continue;
	    for(s[2]='0';s[2]<='9';s[2]++)
	      {
		if(s[2]==s[0]||s[2]==s[1])
		  continue;
		for(s[3]='0';s[3]<='9';s[3]++)
		  {
		    if(s[3]==s[0]||s[3]==s[1]||s[3]==s[2])
		      continue;

		    h1=hit(s,s1);b1=blow(s,s1);
		    h2=hit(s,s2);b2=blow(s,s2);

		    if(h1!=h2 || b1!=b2)
		      {
			//printf("A=%s\n",s);
			sscanf(s,"%d",&ret);
			return(ret);
		      }
		  }
	      }
	  }
    }
}

int solve()
{
  int i,j,k,l,cnt,min_,c,rc,ret[2];

  min_=10000;
  cnt=0;
  for(i=0;i<10;i++)
    for(j=0;j<10;j++)
      for(k=0;k<10;k++)    
	for(l=0;l<10;l++)
	  {
	    c=flag[i][j][k][l];
	    if(N==c)
	      {
		if(cnt < 2)
		  {
		    ret[cnt]=i*1000+j*100+k*10+l;
		  }
		cnt++;
		//printf("%04d=%d :(%d)\n",i*1000+j*100+k*10+l,c,cnt);
	      }
	  }
  //printf("CNT=%d\n",cnt);
  if(cnt==0)
    return(-1);
  else if(cnt==1)
    return(ret[0]);
  else if(cnt==2)
    //return(ret[0]);
    return(calc_critical(ret[0],ret[1]));
  else
    return(-1);
}
main()
{
  int i,h,b,ret;
  char attempt[5];

  while(scanf("%d",&N) && N)
    {
      clear();

      for(i=0;i<N;i++)
	{
	  scanf("%s %d %d",attempt,&h,&b);
	  check(attempt,h,b);
	}
      ret=solve();
      if(ret==-1)
	printf("????\n");
      else
	printf("%04d\n",ret);
    }
  return(0);
}