December 12, 2020

# Advent of Code 2020 day 6

First steps with Attoparsec

Day 6 was another input file of groups separated by blank lines. As I mentioned on day 4, this isn't what Megaparsec is good for, so time to try out Attoparsec.

Without space consumers to worry about, and therefore more control over how and when whitespace is consumed, the parser ended up much neater than the Megaparsec version would have been. Conversely, it's a quite fragile parser: changes in the positioning of whitespace would cause the parsing to fail.

blankLines = skipMany1 endOfLine

personP = S.fromList <$> many1 letter groupP = sepBy1 personP endOfLine groupsP = sepBy groupP blankLines  I think that's quite readable: a person is a set of letters. A group is a collection of people, separated by single newlines. Groups are separated by at least one blank line. Given a list of list of sets of questions, we're back to territory where the code is much shorter than the explanation. I can find all the questions answered by a group by finding the S.unions of the group; I count them with S.size. That's mappped over all the groups and the counts summed. part1 groups = sum$ map (S.size . S.unions) groups


Part 2 is the same, only there isn't an S.intersections function already in the library (what would the base case be, for a general Foldable?). So I had to build one.

part2 groups = sum \$ map (S.size . intersections) groups

intersections :: Ord a => [S.Set a] -> S.Set a
intersections group = foldl S.intersection (head group) group


## Code

You can find the code here or on Gitlab.