import System.IO import Data.List.Split data Cycle = Noop | Addx1 | Addx2 Int deriving (Show) parseInstr :: String -> [Cycle] parseInstr ('n':_) = [Noop] parseInstr ('a':xs) = [Addx1,Addx2 dx] where dxs = last $ splitOn " " xs dx = read dxs :: Int parseAsm :: String -> [Cycle] parseAsm = concat . map parseInstr . lines computeX :: Int -> Cycle -> Int computeX x (Addx2 dx) = x + dx computeX x _ = x drawCRT :: [Bool] -> (Int, Int) -> [Bool] drawCRT crt (c,x) = sx ++ [draw] ++ (tail xs) where (sx,xs) = splitAt c crt sprite = [x-1,x,x+1] col = (c `mod` 40) draw = elem col sprite printCRT :: [Bool] -> String printCRT = concat . map (++"\n") . chunksOf 40 . map crtchr where crtchr False = '.' crtchr True = '#' handler :: String -> String handler s = (show $ sum score) ++ "\n" ++ (printCRT crt) ++ "\n" where cycles = parseAsm s xhs = scanl computeX 1 cycles sigstr = zipWith (*) [1..] xhs score = map ((0:sigstr) !!) [20,60..220] crt = foldl drawCRT (replicate 240 False) (zip [0..239] xhs) main :: IO () main = do interact handler