65 lines
1.2 KiB
Haskell
65 lines
1.2 KiB
Haskell
|
import System.IO
|
||
|
|
||
|
import Data.List.Split
|
||
|
|
||
|
import Debug.Trace
|
||
|
|
||
|
|
||
|
|
||
|
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
|
||
|
|
||
|
|