// Arup Guha
// 4/8/2023 (started a couple days ago)
// Solution to 2023 March USACO Bronze Problem: Moo Language
import java.util.*;

public class moolanguage {

	public static ArrayList<String> nouns;
	public static ArrayList<String> tverbs;
	public static ArrayList<String> intverbs;
	public static ArrayList<String> conj;
	public static int numC;
	public static int numP;
	public static int nIdx, tIdx, iIdx, cIdx;
	
	public static void main(String[] args) {
	
		Scanner stdin = new Scanner(System.in);
		int nC = stdin.nextInt();
		
		// Process cases.
		for (int loop=0; loop<nC; loop++) {
		
			// Get basic stats.
			int numW = stdin.nextInt();
			numC = stdin.nextInt();
			numP = stdin.nextInt();
		
			// Doing four lists for readability...
			// Shorter code would be array of lists.
			nouns = new ArrayList<String>();
			tverbs = new ArrayList<String>();
			intverbs = new ArrayList<String>();
			conj = new ArrayList<String>();
			
			// Process words.
			for (int i=0; i<numW; i++) {
			
				String w = stdin.next();
				char t = stdin.next().charAt(0);
				
				if (t == 'n') nouns.add(w);
				if (t == 'i') intverbs.add(w);
				if (t == 't') tverbs.add(w);
				if (t == 'c') conj.add(w);
			}

			// Get optimal balance of transitive and intransitive verbs.
			int[] bestVerbs = getBest();
			int useT = bestVerbs[0];
			int useI = bestVerbs[1];
			
			// These are my indexes into the lists.
			nIdx = 0; tIdx = 0; iIdx = 0; cIdx = 0;
			
			// Get best arrangement with useI intransitive and useT transitive.
			ArrayList<sentence> all = solve(useI, useT);
			
			int sz = 0;
			for (sentence z: all) sz += z.numWords();
			
			// # of words.
			System.out.println(sz);
			
			// And rest of the result.
			if (all.size() > 0) {
				all.get(0).print();
				for (int i=1; i<all.size(); i++) {
					System.out.print(" ");
					all.get(i).print();
				}
			}
			System.out.println();
		}
	}
	
	// Returns the # of transitive verbs, # of intransitive verbs and max words, in an array
	// of size 3. With this information an optimal solution can be easily built.
	public static int[] getBest() {
		
		// We store all 3 metrics here, separately.
		int maxW = 0, bestT = -1, bestInt = -1;
		
		// Try i for the # of transitive verbs.
		for (int i=0; i<=tverbs.size(); i++) {
			
			// Returns max words with i transitive verbs.
			int[] tmp = getWords(i);
			
			if (tmp == null) continue;
			
			// If this is the best, update everything.
			if (tmp[0] > maxW) {
				maxW = tmp[0];
				bestT = i;
				bestInt = tmp[1];
			}
		}
		
		// These are the metrics we need to return.
		return new int[]{bestT, bestInt, maxW};
	}
	
	// Given that we use exactly numT transitive verbs, this returns the max number of words
	// we can use and the number of intransitive verbs to get that result. Returns null if it's
	// impossible to use this many transitive verbs.
	public static int[] getWords(int numT) {
		
		// Not enough to match.
		if (nouns.size() < 2*numT) return null;

		// Fewest sentences we could form.
		int useConj = Math.min(numT/2, conj.size());
		int minS = numT - useConj;
		
		// Can't do it.
		if (minS > numP) return null;
		
		// How many nouns we have left.
		int nLeft = nouns.size() - 2*numT;
		
		// How many conjunctions we have left.
		int conjLeft = conj.size() - useConj;
		
		// Sentences we can form.
		int sentLeft = numP-minS;
		
		// This is true if we have an odd sentence out which we can match with a conjunction.
		boolean haveExtra = numT%2 == 1;
		
		// # of intransitive verbs we can use.
		int intLeft = intverbs.size();
		
		// Now I peel off intransitive verbs, separately.
		while (sentLeft > 0 || (sentLeft == 0 && haveExtra) ) {
			
			
			// Special case, we can add one sentence with a conjunction without adding
			// to the total # of sentences.
			if (haveExtra && conjLeft > 0 && intLeft > 0 && nLeft > 0) {
				conjLeft--;
				intLeft--;
				nLeft--;
				haveExtra = false;
			}
			
			// Two new sentences merged together...
			else if (sentLeft>0 && conjLeft > 0 && intLeft > 1 && nLeft > 1) {
				conjLeft--;
				intLeft -=2;
				nLeft-=2;
				sentLeft--;
			}
			
			// One sentence.
			else if (sentLeft>0 && intLeft > 0 && nLeft > 0) {
				sentLeft--;
				nLeft--;
				intLeft--;
			}
			else
				break;
		}
		
		// Calculate the number of words...easy for no transitive verbs.
		int numThisW = 0;
		if (numT == 0) 	numThisW = conj.size()-conjLeft + intverbs.size()-intLeft + nouns.size()-nLeft;
		
		// Trickier, we have to deal with commas for added nouns, in particular...
		else {
			int prevNoun = nouns.size()-nLeft;
			int maxNounAdd = Math.min(nLeft, numC);
			numThisW = numT + conj.size()-conjLeft + intverbs.size()-intLeft + prevNoun + maxNounAdd;
		}
		
		return new int[]{numThisW, intverbs.size()-intLeft};
	}
	
	// Returns an optimal set of sentneces for useI intransitive verbs and useT transitive verbs.
	public static ArrayList<sentence> solve(int useI, int useT) {
		
		ArrayList<sentence> res = new ArrayList<sentence>();
		
		// First we form sentences with intransitive verbs.
		for (iIdx=0; iIdx<useI; iIdx++) {
			sentence next = new sentence();
			next.addWord(nouns.get(nIdx++));
			next.addWord(intverbs.get(iIdx));
			res.add(next);
		}
		
		// Next with transitive verbs.
		for (tIdx=0; tIdx<useT; tIdx++) {
			sentence next = new sentence();
			next.addWord(nouns.get(nIdx++));
			next.addWord(tverbs.get(tIdx));
			next.addWord(nouns.get(nIdx++));
			res.add(next);
		}
		
		// Special case.
		if (res.size() == 0) return res;
		
		// Tack on as many nouns to a transitive sentence as possible.
		if (useT > 0) {
			while (nIdx < nouns.size() && cIdx < numC) {
				res.get(res.size()-1).addWord(nouns.get(nIdx++));
				cIdx++;
			}
		}
		
		// Now just add conjunctions.
		ArrayList<sentence> newres = new ArrayList<sentence>();
		
		// i is index into cur, j is index into conjunctions.
		int i = 0, j = 0;
		
		// Puts in as many conjunctions as possible.
		while (i < res.size()) {
			
			// Put together two sentences.
			if (j < conj.size() && i < res.size()-1) {
				sentence tmp = new sentence(res.get(i), res.get(i+1), conj.get(j++));
				newres.add(tmp);
				i += 2;
			}
			
			// Just use one.
			else {
				newres.add(res.get(i));
				i++;
			}
		}
		
		// Ta da!
		return newres;	
	}
}

class sentence {

	public boolean isComp;
	public ArrayList<String> part1;
	public ArrayList<String> part2;
	public String con;
	
	public sentence() {
		isComp = false;
		part1 = new ArrayList<String>();
		part2 = null;
		con = null;
	}
	
	// a and b are simple
	public sentence(sentence a, sentence b, String mycon) {
		isComp = true;
		part1 = new ArrayList<String>();
		for (String x: a.part1) part1.add(x);
		part2 = new ArrayList<String>();
		for (String x: b.part1) part2.add(x);
		con = mycon;
	}
	
	// Prints how they want.
	public void print() {
		
		// For spacing.
		System.out.print(part1.get(0));
		for (int i=1; i<part1.size(); i++) {
			System.out.print(" "+part1.get(i));
			if (i>=2 && i<part1.size()-1) System.out.print(",");
		}
		
		if (!isComp) {
			System.out.print(".");
			return;
		}
		
		System.out.print(" "+con);
		
		for (int i=0; i<part2.size(); i++) {
			System.out.print(" "+part2.get(i));
			if (i>=2 && i<part2.size()-1) System.out.print(",");
		}
		System.out.print(".");
		
	}
	
	// Only for simple...
	public void addWord(String s) {
		part1.add(s);
	}
	
	// Returns # of words in this sentence.
	public int numWords() {
		if (part2 == null) return part1.size();
		return part1.size() + part2.size() + 1;
	}
}