Problem: A PIN code is a string that consists of exactly 4 digits. Examples of possible PIN codes: 7013, 0000 and 0990. Please note that the PIN code can begin with any digit, even with 0.

Polycarp has n (2 ≤ n ≤ 10) bank cards, the PIN code of the i-th card is p_i.

Polycarp has recently read a recommendation that it is better to set different PIN codes on different cards. Thus he wants to change the minimal number of digits in the PIN codes of his cards so that all n codes would become different.

Formally, in one step, Polycarp picks i-th card (1 ≤ i ≤ n), then in its PIN code p_i selects one position (from 1 to 4), and changes the digit in this position to any other. He needs to change the minimum number of digits so that all PIN codes become different.

Polycarp quickly solved this problem. Can you solve it?

Input

The first line contains integer t (1 ≤ t ≤ 100) — the number of test cases in the input. Then test cases follow.

The first line of each of t test sets contains a single integer n (2 ≤ n ≤ 10) — the number of Polycarp's bank cards. The next n lines contain the PIN codes p_1, p_2, ..., p_n — one per line. The length of each of them is 4. All PIN codes consist of digits only.

Output

Print the answers to t test sets. The answer to each set should consist of a n + 1 lines

In the first line print k — the least number of changes to make all PIN codes different. In the next n lines output the changed PIN codes in the order corresponding to their appearance in the input. If there are several optimal answers, print any of them.

Example

Input


3
2
1234
0600
2
1337
1337
4
3139
3139
3139
3139


Output


0
1234
0600
1
1337
1237
3
3139
3138
3939
6139

Solution (in JAVA):

Solution:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class Main {
	static  ArrayList<Pair>adj[];
	static int memo2[];
	static char c1[][];
	static HashMap<Long,Integer> hs=new HashMap<>();
	static PrintWriter out=new PrintWriter(System.out);
	public static void main(String[] args) throws Exception {
	Scanner sc=new Scanner(System.in);
	int t=sc.nextInt();
	while(t-->0) {
	int n=sc.nextInt();
	HashMap<Integer,Integer> map=new HashMap();
	int a[]=new int[n];
	String b[]=new String[n];
	for (int i = 0; i < a.length; i++) {
		a[i]=sc.nextInt();
	map.put(a[i], map.getOrDefault(a[i], 0)+1);
	}
	ArrayList<Integer> l=new ArrayList<Integer>();
	int count=0;
	for (int i = 0; i < a.length; i++) {
if(map.get(a[i])>1) 
		for (int j = 0; j <=9; j++) {
			int x=a[i]-a[i]%10;
		int last=a[i]%10;
		last=(last+j)%10;
		if(!map.containsKey(x+last)) {
			map.put(x+last,1);
			l.add(x+last);
			count++;
			map.put(a[i], map.get(a[i])-1);
		break;
		}
			}
else
	l.add(a[i]);
		
	}
	System.out.println(count);
	ArrayList<String> l1=new ArrayList<String>();
	for(int x:l) {
	String s=x+"";
	if(s.length()==3) {
	s="0"+x;
	
	}
	else if(s.length()==2) {
		s="00"+x;	
	}
	else if(s.length()==1) {
		s="000"+x;	
	}
	l1.add(s);
	}
	for(String s:l1) {
		System.out.println(s);
	}
	
	
	}
}
	static  class Triple implements Comparable<Triple>{
		int cost;
		int totalcost;
		int idx;
		public Triple(int a,int b,int c) {
			cost=b;
			totalcost=c;
			idx=a;
		}
		@Override
		public int compareTo(Triple o) {
		if(this.totalcost!=o.totalcost)
			return this.totalcost-o.totalcost;
		else
			return this.cost-o.cost;
			
		}
		
	}
	private static int dp(int cur, int size) {
	if(size==k) {
		return 1;
	}
	if(memo[cur][size]!=-1) {
		return memo[cur][size];
	}
	long count=0;
	for(int i=1 ; i*cur<=n ; i++) {
			count+=dp(i*cur,size+1);
		
	}
	return memo[cur][size]=(int) count;
	}
	static TreeSet<Long> primeFactors(long N)		// O(sqrt(N) / ln sqrt(N))
	{
		TreeSet<Long> factors = new TreeSet<Long>();		//take abs(N) in case of -ve integers
		int idx = 0, p = primes.get(idx);

		while(p * p <= N)
		{
			while(N % p == 0) { factors.add((long) p); N /= p; }
			if(primes.size()>idx+1)
			p = primes.get(++idx);
			else
				break;
		}

		if(N != 1)						// last prime factor may be > sqrt(N)
			factors.add(N);				// for integers whose largest prime factor has a power of 1
		return factors;
	}
	
	static boolean visited[];
	static int k;
	static int bfs(int s)
	{
		Queue<Integer> q = new LinkedList<Integer>();
		q.add(s);
		int count=0;
		int maxcost=0;
		int dist[]=new int[n];
		dist[s]=0;
		while(!q.isEmpty())
		{
			
			int u = q.remove();
			if(dist[u]==k) {
				break;
			}
			for(Pair v: adj[u])
			{	
				maxcost=Math.max(maxcost, v.cost);
			
			
			
			if(!visited[v.v])	{
				
				visited[v.v]=true;
				q.add(v.v);
				dist[v.v]=dist[u]+1;
				maxcost=Math.max(maxcost, v.cost);
			}
			}	
			
		}
		return maxcost;
	}
	public static boolean FindAllElements(int n, int k) {
	 int sum = k;  
     int[] A = new int[k];  
      Arrays.fill(A, 0, k, 1);  
        
      for (int i = k - 1; i >= 0; --i) {  
      
           while (sum + A[i] <= n) {  
      
              sum += A[i];  
              A[i] *= 2;  
          }  
      }  
      if(sum==n) {
      	return true;
      }
      else
    	return false; 
	}
	
	static int[][] memo;
	static long b[];

	static class Pair implements Comparable<Pair>{
		int v;
		int cost;
		public Pair(int x , int y) {
		v=x;
		cost=y;
		}
		@Override
		public int compareTo(Pair o) {
		return o.cost-this.cost;
		}
		
	}
	static long bs(long x) {
		long high=(long) 1e7;
		long low=0;
		long idxend=0;
		long idxstart=0;
		if(hs.containsKey(x)) {
			return hs.get(x);
		}
		while(high>=low) {
			long mid=(high+low)>>1;
			long range=((mid)*(mid-1));
			range/=2;
			range++;
			if(range>x) {
				high=mid-1;
				
			}
			else {
				low=mid+1;
			idxstart=mid;
			}
		}
	return idxstart;	
	}
	static boolean vis2[][];
	
	static class SegmentTree {		// 1-based DS, OOP
		
		int N; 			//the number of elements in the array as a power of 2 (i.e. after padding)
		int[] array, sTree, lazy;
		
		SegmentTree(int[] in)		
		{
			array = in; N = in.length - 1;
			sTree = new int[N<<1];		//no. of nodes = 2*N - 1, we add one to cross out index zero
			lazy = new int[N<<1];
			build(1,1,N);
		}
		
		void build(int node, int b, int e)	// O(n)
		{
			if(b == e)					
				sTree[node] = array[b];
			else						
			{
				int mid = b + e >> 1;
				build(node<<1,b,mid);
				build(node<<1|1,mid+1,e);
				sTree[node] = sTree[node<<1]+sTree[node<<1|1];
			}
		}
		
		
		void update_point(int index, int val)			// O(log n)
		{
			index += N - 1;				
			sTree[index] += val;			
			while(index>1)				
			{
				index >>= 1;
				sTree[index] = sTree[index<<1] + sTree[index<<1|1];		
			}
		}
		
		
		void update_range(int i, int j, int val)		// O(log n) 
		{
			update_range(1,1,N,i,j,val);
		}
		
		void update_range(int node, int b, int e, int i, int j, int val)
		{
			if(i > e || j < b)		
				return;
			if(b >= i && e <= j)		
			{
				sTree[node] += (e-b+1)*val;			
				lazy[node] += val;				
			}							
			else		
			{
				int mid = b + e >> 1;
				propagate(node, b, mid, e);
				update_range(node<<1,b,mid,i,j,val);
				update_range(node<<1|1,mid+1,e,i,j,val);
				sTree[node] = sTree[node<<1] + sTree[node<<1|1];		
			}
			
		}
		void propagate(int node, int b, int mid, int e)		
		{
			lazy[node<<1] += lazy[node];
			lazy[node<<1|1] += lazy[node];
			sTree[node<<1] += (mid-b+1)*lazy[node];		
			sTree[node<<1|1] += (e-mid)*lazy[node];		
			lazy[node] = 0;
		}
		
		int query(int i, int j)
		{
			return query(1,1,N,i,j);
		}
		
		int query(int node, int b, int e, int i, int j)	// O(log n)
		{
			if(i>e || j <b)
				return 0;		
			if(b>= i && e <= j)
				return sTree[node];
			int mid = b + e >> 1;
			propagate(node, b, mid, e);
			int q1 = query(node<<1,b,mid,i,j);
			int q2 = query(node<<1|1,mid+1,e,i,j);
			return q1 + q2;	
					
		}
	
	}
	static long mod=(long) (1e9+7);
	static boolean f2=false;
	static long[][] matMul(long[][] a2, long[][] b, int p, int q, int r)	//C(p x r) = A(p x q) x (q x r) -- O(p x q x r)
	{
		long[][] C = new long[p][r];
		for(int i = 0; i < p; ++i) {
			for(int j = 0; j < r; ++j) {
				for(int k = 0; k < q; ++k) {
					C[i][j] = (C[i][j]+(a2[i][k]%mod * b[k][j]%mod))%mod;
		 C[i][j]%=mod;
				}
		
			}
		}
		return C;
	}
		static long query[];
	static long last1=0;
	static TreeSet<Long> x1;
	static HashMap<Long,Long> map;
	static long max=0;
	static int first=0;
	
	
	
		
		
		
		

		
	
	static ArrayList<Pair> a1[];
	static int memo1[];
	
	static boolean vis[];
	static TreeSet<Integer> set=new TreeSet<Integer>();
	
	static long modPow(long ways, long count, long mod)	// O(log e)
	{
		ways %= mod;
		long res = 1;
		while(count > 0)
		{
			if((count & 1) == 1)
				res = (res * ways) % mod;
			ways = (ways * ways) % mod;
			count >>= 1;
		}
		return res%mod;
	}
	
	
	
	static  int  dx[] = {0,0,0,3,3,3,6,6,6};
	static int dy[] = {0,3,6,0,3,6,0,3,6};
	static long[] a;
	static int n;
	static int s;
	static boolean f[];

	static long gcd(long ans,long b) {
		if(b==0) {
			return ans;
		}
		return gcd(b,ans%b);
	}
	static int[] isComposite;
	static int[] valid;
	
	static ArrayList<Integer> primes;
	static ArrayList<Integer> l;
	static void sieve(int N)	// O(N log log N) 
	{
		isComposite = new int[N+1];					
		isComposite[0] = isComposite[1] = 1;			// 0 indicates a prime number
		primes = new ArrayList<Integer>();
		l=new ArrayList<>();
		valid=new int[N+1];
		for (int i = 2; i <= N; ++i) 					//can loop till i*i <= N if primes array is not needed O(N log log sqrt(N)) 
			if (isComposite[i] == 0) 					//can loop in 2 and odd integers for slightly better performance
			{
				primes.add(i);
				l.add(i);
				valid[i]=1;
				
				for (int j = i*2; j <=N; j +=i) {	// j = i * 2 will not affect performance too much, may alter in modified sieve
						isComposite[j] = 1;
						
						
						
				      
					}
			}
		
		for(int i=0 ; i<primes.size() ; i++) {
			for(int j:primes) {
				if(primes.get(i)*j>N) {
					break;
				}
				valid[primes.get(i)*j]=1;
			}
		}
	}
	static int c;
	static class UnionFind {                                              
		int[] p, rank, setSize;
		int numSets;

		public UnionFind(int N) 
		{
			p = new int[numSets = N];
			rank = new int[N];
			setSize = new int[N];
			for (int i = 0; i < N; i++) {  p[i] = i; setSize[i] = 1; }
		}

		public int findSet(int i) { return p[i] == i ? i : (p[i] = findSet(p[i])); }

		public boolean isSameSet(int i, int j) { return findSet(i) == findSet(j); }

		public void unionSet(int i, int j) 
		{ 
			if (isSameSet(i, j)) 
				return;
			numSets--; 
			int x = findSet(i), y = findSet(j);
			if(rank[x] > rank[y]) { p[y] = x; setSize[x] += setSize[y]; }
			else
			{	p[x] = y; setSize[y] += setSize[x];
				if(rank[x] == rank[y]) rank[y]++; 
			} 
		}

		public int numDisjointSets() { return numSets; }

		public int sizeOfSet(int i) { return setSize[findSet(i)]; }
	}
	public static int[] schuffle(int[] a2) {
		for (int i = 0; i < a2.length; i++) {
			int x=(int)(Math.random()*a2.length);
		int temp=a2[x];
		a2[x]=a2[i];
		a2[i]=temp;
		}
		return a2;
	}
		static int V;
	static int INF=(int) 1E9;
		
		static class Edge2 
		{
			int node;
		long cost;
			long next;
			Edge2(int a, int c,Long long1) { node = a;	cost = long1; next=c;}
			
		}
static class Scanner {
		StringTokenizer st;
		BufferedReader br;
 
		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}
 
		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}
 
		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}
 
		public String nextLine() throws IOException {
			return br.readLine();
		}
 
		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}
 
		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}
 
		public char nextChar() throws IOException {
			return next().charAt(0);
		}
 
		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}
 
		public boolean ready() throws IOException {
			return br.ready();
		}
 
		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}	
}