import string WIN = float('inf') LOSE = float('-inf') def ag(x,y): if x == LOSE or y == LOSE: return LOSE else: return max(x,y) t = int(input()) for case in range(1,t+1): s = f"Case #{case}:" r, c = map(int, input().split()) data = ['#'*(c+2)] for _ in range(r): data.append('#'+input()+'#') data.append('#'*(c+2)) starts = {} finishes = {} for i in range(r+2): for j in range(c+2): if data[i][j] in string.ascii_lowercase: starts[i,j] = data[i][j] elif data[i][j] in string.ascii_uppercase: finishes[i,j] = data[i][j] reachable = [[{f:None for f in finishes} for _ in range(c+2)] for _ in range(r+2)] def safe_path(r1,c1,goal,old,n): if (r1,c1) == goal: return WIN elif (r1,c1) in old: return old[r1,c1] elif data[r1][c1] == '*': return LOSE elif data[r1][c1] == '#': return n+1 elif reachable[r1][c1][goal] != None: return reachable[r1][c1][goal] new_old = old.copy() new_old[r1,c1] = n v_result = ag(safe_path(r1-1,c1,goal,new_old,n-1),safe_path(r1+1,c1,goal,new_old,n-1)) h_result = ag(safe_path(r1,c1-1,goal,new_old,n-1),safe_path(r1,c1+1,goal,new_old,n-1)) result = max(v_result,h_result) if result < n+1: result = LOSE if result in (WIN, LOSE): pass #reachable[r1][c1][goal] = result return result wins = [] for start in starts: for finish in finishes: if safe_path(start[0],start[1],finish,{},0) == WIN: wins.append(f" {starts[start]}{finishes[finish]}") if wins == []: wins.append(" NONE") s += ''.join(sorted(wins)) print(s)