Solution to East Central North America 2000, Problem D: Stacking Cubes. > import Array > import Monad > import List > import ReaderMonad A stacking pattern is represented here as a list of rows of numbers. A cube stack is a 3d array of 1's. The first dimension goes along the left wall, the second the right wall, and the third the height. > type SP = [[Int]] > type Stack = Array (Int,Int,Int) Int > maxindex = 20 :: Int > maxrange :: ((Int,Int,Int),(Int,Int,Int)) > maxrange = ((1,1,1),(maxindex,maxindex,maxindex)) This creates the cube stack from a stacking pattern. > makeStack :: SP -> Stack > makeStack sp = accumArray (+) 0 maxrange alist > where alist = concat $ zipWith rowf [1..] sp > -- rowf processes the n-th row r > rowf n r = concat $ zipWith colf [1..] r > where colf m c = map (\z->((n,m,z), 1)) [1..c] > -- colf processes the m-th column c This creates the stacking pattern from a cube stack. (Why do we not care about rotations? You will see in a minute.) > makeSP :: Stack -> SP > makeSP s = takeWhile (not.null) $ map makeRow [1..maxindex] > where makeRow n = takeWhile (/= 0) $ map makeCol [1..maxindex] > where makeCol m = sum [ s!(n,m,z) | z <- [1..maxindex] ] We now take care of rotations. This is simply remapping the index triples! > rightRotate :: Stack -> Stack > rightRotate = ixmap maxrange (\(y,z,x)->(x,y,z)) > leftRotate :: Stack -> Stack > leftRotate = ixmap maxrange (\(z,x,y)->(x,y,z)) > main = do n <- readLn > if n==0 > then return () > else do sp <- sequence (replicate n getRow) > let s = makeStack sp > putStrLn $ showSP $ makeSP $ leftRotate s > putStrLn $ showSP $ makeSP $ rightRotate s > putStrLn "" > main > where getRow = do l <- getLine > rreadIO rowreader1 l > rowreader1 = do n <- reader > ns <- rowreader > return (n:ns) > rowreader = rowreader1 `mplus` (return []) > showSP sp = concatMap showRow sp > showRow row = (concat $ intersperse " " $ map show row) ++ "\n"