import Data.List.Split

data OpCode
  = Noop
  | AddX Int
  deriving (Show, Eq)

main :: IO ()
main = do
  input <- parse . lines <$> readFile "input"
  let c = 1 : 1 : 1 : cycles 1 input
  let vals = [20, 60, 100, 140, 180, 220]
  print $ sum [i * c !! i | i <- vals]
  putStrLn $ printscr (tail c)

parse :: [String] -> [OpCode]
parse (l:ls)
  | l == "noop" = Noop : parse ls
  | head len2 == "addx" = AddX (read $ len2 !! 1) : parse ls
  where
    len2 = words l
parse _ = []

cycles :: Int -> [OpCode] -> [Int]
cycles x (Noop:cs) = x : cycles x cs
cycles x (AddX y:cs) = (x + y) : (x + y) : cycles (x + y) cs
cycles _ _ = []

printscr :: [Int] -> String
printscr pxs = concat [zipWith f (ls !! x) [0 ..] ++ "\n" | x <- [0 .. 5]]
  where
    f x y =
      if abs (x - y) <= 1
        then '#'
        else '.'
    ls = chunksOf 40 pxs
