do
  content <- lines <$> input 10
  print $ part1 content
  putStr $ part2 content
  where
    state = catMaybes . flip evalState (0, 1) . sequence . map instruction . parse
    part1 = sum . calculateSignalStrength . state
    part2 = unlines . splitCRTLines . drawCRT . ((1,1):) . map (first (+1)) . state
go 20
  where
singleton . strength c $ every20th c xs
    go cycle xs = (strength cycle $ every20th cycle xs) : (go (cycle + 40) . snd $ every20th cycle xs)
    strength cycle = (*cycle) . snd . last . fst
    every20th cycle = span ((<cycle) . fst)
data Instruction = AddX Int | Noop
mempty
drawCRT ((c, x):[]) = foldr' (\a b -> (drawPixel a x) : b) [] [c..240]
drawCRT ((ac, ax):r@(bc, bx):xs) = (foldr' (\a b -> (drawPixel a ax) : b) [] [ac..bc-1]) ++ drawCRT (r:xs)
go
  where
[[]]
    go x = (fst $ crtLine x) : go (snd $ crtLine x)
    crtLine = splitAt 40
1 = '#'
  | otherwise = '.'
  where
    index = abs (column - y)
    column = (x - 1) `mod` 40
2
cycles Noop = 1
type Cycle = Int
type RegX = Int
do
  (cycle, regx) <- get
  let newCycle = cycle + cycles x
  case x of
    Noop -> do
      put (newCycle, regx)
      pure Nothing
    (AddX a) -> do
      let newSt = (newCycle, regx + a)
      put newSt
      pure $ Just newSt
do
  string "noop"
  pure Noop
do
  string "addx"
  skipSpaces
  n <- read <$> munch1 num
  pure $ AddX n
  where
    num c = isDigit c || c == '-'
choice [parseNoop, parseAddX]
map (fst . head . readP_to_S parseInstruction)