Day 10 of Advent of Code is the first day of the year of pseudo-assembly.
As a literate Haskell post, we’ll start with a couple of imports.
import Control.Monad.Writer (execWriter,tell,foldM)
import Data.List.Split (chunksOf)
So ok, this is assembly language, but it’s barely interesting. It’s certainly not Turing-complete as usual. It merely maintains an accumulator. Its only distinctive feature is that its two operations have distinct cycle lengths. We’re not going to track them directly. Instead, we’ll generate the list of values the accumulator takes, per cycle.
toSignal :: String -> [Int]
lines -> ls) = undefined : execWriter (foldM go 1 ls)
toSignal (where
"noop" = tell [x] *> pure x
go x words -> ["addx",read -> addx]) =
go x (*> pure (x + addx) tell [x,x]
Part 1 of the puzzle asks us to sum the signal’s value at certain times.
part1 :: [Int] -> Int
= sum [ i * signal !! i | i <- [20,60,100,140,180,220] ] part1 signal
Part 2 asks us when the signal coincides with an electron beam scan with rollover. The definition of “coincides” is “at a distance of 0 or 1”. We present the result in monospace textual form for better readability.
part2 :: [Int] -> [String]
= chunksOf 40 . map ((".#" !!) . fromEnum) .
part2 zipWith close (cycle [0..39]) . tail
where close a b = abs (b-a) <= 1
A little wrapper puts it all together.
main :: IO ()
= do
main <- toSignal <$> getContents
signal print (part1 signal)
putStr (unlines (part2 signal))
This concludes today’s puzzle. See you tomorrow!