import Data.Array import Data.Function (on) import Data.List (minimumBy) import qualified Data.Map as M import Control.Monad (liftM, forM_) import Text.Printf sink :: Array (Int,Int) Int -> Array (Int,Int) (Int,Int) sink m = ret where ret = array bm [(i, f i) | i<-indices m] bm = bounds m f p@(x,y) | all (\(_,x) -> x >= v) xs = p | otherwise = ret ! (fst $ minimumBy (compare `on` snd) xs) where v = m ! p xs = [(p, m!p) | p<-[(x,y-1),(x-1,y),(x+1,y),(x,y+1)], inRange bm p] solve :: Array (Int,Int) Int -> Array (Int,Int) Char solve m = array bm (g M.empty 'a' [(x,y) | y<-[y0..y1], x<-[x0..x1]]) where bm@((x0,y0),(x1,y1)) = bounds m g _ c [] = [] g tbl c (p:ps) = case M.lookup s tbl of Just c' -> (p, c') : g tbl c ps Nothing -> (p, c) : g (M.insert s c tbl) (succ c) ps where s = sinkTable ! p sinkTable = sink m main :: IO () main = do t <- liftM read getLine forM_ [(1::Int)..t] $ \n -> do [h,w] <- liftM (map read . words) getLine rows <- sequence (replicate h (liftM (map read . words) getLine)) let m = array ((1,1),(w,h)) [((x,y),v) | (y,row) <- zip [1..h] rows, (x,v) <- zip [1..w] row] ans = solve m printf "Case #%d:\n" n forM_ [1..h] $ \y -> putStrLn $ unwords [[ans!(x,y)] | x<-[1..w]]