// Solution to "Solitaire" by Bob Roos (not yet commented) import java.util.*; import java.io.*; public class Solitaire { static BufferedReader in; static StringTokenizer tok; static int n; // number of problem instances static int players; // number of players static int cards[][]; // cards held by each player static int count[]; static int pos[]; static boolean discard[]; static int last[]; static int cycle[]; static int discardCount; ///////////////////////////////////////////////////////////////////// // Main: read in the input, public static void main(String[] args) throws IOException { in = new BufferedReader(new InputStreamReader(System.in)); n = Integer.parseInt(in.readLine().trim()); for (int instance = 1; instance <= n; instance++) { String line = in.readLine().trim(); tok = new StringTokenizer(line); players = Integer.parseInt(tok.nextToken()); cards = new int[players][53]; cards[0][0] = 52; for(int i = 1; i < players; i++) cards[i][0] = 0; for(int i = 1; i <= 52; i++) cards[0][i] = Integer.parseInt(tok.nextToken()); System.out.print("Case "+instance+": "); simulate(); } } ///////////////////////////////////////////////////////////////////// public static void simulate() { boolean change; count = new int[players]; pos = new int[players]; discard = new boolean[players]; last = new int[players]; cycle = new int[players]; for (int i = 0; i < players; i++) { count[i] = 1; discard[i] = false; pos[i] = 1; cycle[i] = 0; } change = true; discardCount = 0; while (change) { change = false; // simulate moves in reverse order since discards are processed last: for (int i = players-1; i >= 0; i--) { boolean temp = move(i); change = change || temp; } } if (discardCount < 52) System.out.println("unwinnable"); // discarded only " + discardCount); else { System.out.print(last[0]); for (int i = 1; i < players; i++) System.out.print(" "+last[i]); System.out.println(); } } public static boolean move(int i) { // If no cards, just return "false" (if this game is not winnable, // eventually everyone will return false) if (cards[i][0] == 0) { //System.out.println("Player " + i + ": can't move"); return false; } // Look at current value of "count" and compare to next card: //System.out.print("Player " + i + ": count,pos = " + count[i] +","+pos[i]+"."); //for(int j = 1; j <= cards[i][0]; j++) // System.out.print(cards[i][j]+" "); //System.out.println(); if (count[i] == cards[i][pos[i]]) { if (i < players-1) { //System.out.println("Passing "+cards[i][pos[i]]+" to player " + (i+1)); insert(cards[i][pos[i]],i+1); } //else //System.out.println("Discarding "+cards[i][pos[i]]); if (cards[i][0] == 1) last[i] = cards[i][1]; // Shift everything down to fill in the gap made by removing card: for (int j = pos[i]; j < cards[i][0]; j++) cards[i][j] = cards[i][j+1]; cards[i][0]--; discard[i] = true; cycle[i] = 0; if (i == players-1) discardCount++; if (pos[i] > cards[i][0]) pos[i] = 1; } else pos[i] = pos[i]%cards[i][0]+1; //else System.out.println("Player " + i+ " doesn't see a match"); count[i] = count[i]%13+1; if (count[i] != 1) return true; else { boolean retValue = discard[i]; discard[i] = false; cycle[i]++; if (cycle[i] >= 4*cards[i][0]) return retValue; else return true; } } public static void insert(int value, int playerNum) { if (cards[playerNum][0] == 0) { cards[playerNum][0] = 1; cards[playerNum][1] = value; pos[playerNum] = 1; return; } cards[playerNum][0]++; if (pos[playerNum] == 1) cards[playerNum][cards[playerNum][0]] = value; else { // shift everything forward to make room for new value: for (int j = cards[playerNum][0]; j > pos[playerNum]; j--) cards[playerNum][j] = cards[playerNum][j-1]; pos[playerNum]++; cards[playerNum][pos[playerNum]-1] = value; } return; } }