For once, I didn't use Megaparsec for parsing the data file: just read the file and
digitToInt over it to convert the characters into digits. The built-in
chunksOf splits the raw string into layers.
Part 1 becomes clear through the use of the
count utility function, and the built-in
comparing function to find the layer with the most zeroes.
In part 2, I use
transpose to convert the data from being a layer upon layer of pixels, to being a list of "pixels", but each "pixel" is in fact the value of that pixel in all the layers in the image. I can find the colour of each pixel by dropping all the leading transparent pixels and picking the first of what's left.
I then convert these visible pixels into the strings that will represent them on the screen.
concatMap does the conversion and represents the image as a single one-dimensional string; the
unlines pair reshapes that row into the grid.
import Data.List import Data.List.Split import Data.Char import Data.Ord main :: IO () main = do text <- readFile "data/advent08.txt" let digits = successfulParse text let layers = chunksOf (imageWidth * imageHeight) digits print $ part1 layers putStrLn $ part2 layers imageWidth = 25 imageHeight = 6 part1 layers = (count 1 target) * (count 2 target) where target = minimumBy (comparing (count 0)) layers part2 layers = unlines rows where pixelLayers = transpose layers pixels = map firstVisible pixelLayers image = concatMap showPixel pixels rows = chunksOf imageWidth image firstVisible = head . dropWhile (== 2) showPixel 0 = " " showPixel 1 = "\x2588" count n = length . filter (== n) successfulParse :: String -> [Int] successfulParse input = map digitToInt input