import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.Stack; import java.util.StringTokenizer; class Main { public static int [][] neighbours = {{0,-1},{0,1},{-1,0},{1,0}}; private static class Coordinate { public int x, y; public Coordinate(int x, int y) { this.x=x; this.y=y; } } public static void flood(boolean [][] table, int x, int y, int [][] id, int idToFill) { Stack<Coordinate> stk=new Stack<>(); stk.push(new Coordinate(x,y)); while (!stk.isEmpty()) { Coordinate c=stk.pop(); id[c.x][c.y]=idToFill; for (int [] neighbour : neighbours) { int x1=c.x+neighbour[0]; int y1=c.y+neighbour[1]; if (x1>=0 && x1<table.length && y1>=0 && y1<table[0].length && table[x1][y1]==table[c.x][c.y] && id[x1][y1]==0) stk.push(new Coordinate(x1,y1)); } } } public static void bfs(boolean [][] visited, int x, int y, int [][] id, int idToFind, Set<Integer> neighbourIDs) { Stack<Coordinate> stk=new Stack<>(); stk.push(new Coordinate(x,y)); while (!stk.isEmpty()) { Coordinate c=stk.pop(); visited[c.x][c.y]=true; for (int [] neighbour : neighbours) { int x1=c.x+neighbour[0]; int y1=c.y+neighbour[1]; if (x1>=0 && x1<visited.length && y1>=0 && y1<visited[0].length && !visited[x1][y1]) { if (id[x1][y1]!=idToFind) neighbourIDs.add(id[x1][y1]); else stk.add(new Coordinate(x1,y1)); } } } } public static void main (String [] args) throws Exception { BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); boolean [][] lookup=new boolean [128][4]; for (int i=1;i<16;i++) { char hex = Integer.toHexString(i).charAt(0); char [] bin = Integer.toBinaryString(i).toCharArray(); for (int i2=0;i2<bin.length;i2++) lookup[hex][(4-bin.length)+i2]=bin[i2]=='1'; } char [] ansLookup= {'W','A','K','J','S','D'}; String s; int testCase=1; while (!(s=br.readLine()).equals("0 0")) { StringTokenizer st=new StringTokenizer(s); int H=Integer.parseInt(st.nextToken()); int W=Integer.parseInt(st.nextToken()); boolean [][] table=new boolean [H][W*4]; for (int h=0;h<H;h++) { char [] chs=br.readLine().toCharArray(); for (int w=0;w<W;w++) for (int i2=0;i2<4;i2++) table[h][w*4+i2]=lookup[chs[w]][i2]; } int [][] ID=new int [H][W*4]; //Fill the outside white char from the edge white chars for (int w=0;w<table[0].length;w++) { if (!table[0][w] && ID[0][w]==0) flood(table,0,w,ID,1); if (!table[table.length-1][w] && ID[table.length-1][w]==0) flood(table,table.length-1,w,ID,1); } for (int h=0;h<table.length;h++) { if (!table[h][0] && ID[h][0]==0) flood(table,h,0,ID,1); if (!table[h][table[0].length-1] && ID[h][table[0].length-1]==0) flood(table,h,table[0].length-1,ID,1); } //Flood the remaining white/black char. int currID=2; for (int w=0;w<table[0].length;w++) for (int h=0;h<table.length;h++) if (ID[h][w]==0) { flood(table,h,w,ID,currID++); } ArrayList<Character> ansList=new ArrayList<>(); int [] neighbourCount=new int [currID+30]; for (int h=0;h<table.length;h++) for (int w=0;w<table[0].length;w++) if (table[h][w] && neighbourCount[ID[h][w]]==0) { Set<Integer> set=new HashSet<>(); dfs(new boolean [table.length][table[0].length], h,w,ID,ID[h][w],set); neighbourCount[ID[h][w]]=set.size(); ansList.add(ansLookup[set.size()-1]); } Collections.sort(ansList); StringBuilder ans=new StringBuilder(); ans.append("Case "); ans.append(testCase++); ans.append(": "); for (char c : ansList) ans.append(c); System.out.println(ans.toString()); } } }