Today I suddenly woke up, the lights were turned on by my two year old who was sleeping in our bed because he was crying in his own bed. My first thoughts were turn off those lights and go back to sleep it is the middle of the night. Is it the middle of the night? My alarm didn't go off yet. Was it time almost time, lets check my phone to see how long I've still got left. Damn, my battery was dead, looked at my watch.... 7:20. No good score for today again. After some internal swearing, I got up went to the living room with my son and made some coffee, opened the laptop, and started on day 6.
In today's assignment, we have multiple groups of people, within each group, there are one or more people who answered questions. Each question that is answered with yes is marked by the letter corresponding to that question. There are 26 questions from a to z. For part 1 you have to find the number of questions that have been answered yes to within a group. And sum over all those numbers for all the groups.
split :: String -> [[[Char]]]
split = (map (filter ((>0) .length) . splitOn "\n") . splitOn "\n\n")
-- Map over all groups, within the group take all letters,
-- deduplicate(nub), get length. Sum over all lengths
solve1 = sum . map (length . nub . concat)
-- Map over all groups, make tupke with number of people and all letters)
-- Map over tuples. sort and group the letters.
-- Get Length of groups, count lengths which are same as number of people. Sum count
solve2 - sum . map (\(c, a) -> (count (==c) . map length .group .sort) a) . map ((\x -> (length, concat x)))
My quick and dirty (without the comments of course). Part 1 looks fine, but you kind of need the comments to see what is going on. Part 2 followed the idea of part 1, but added the changed restrictions, now we have to get the number of questions in a group that are answered with yes by all people. As you can see this turned out quite ugly and complex.
After solving this day, increasing one spot in the leaderboard, I look at the problem again. I thought that treating the letters as sets would allow me to find the answers more easy. This is the result after the refactoring
-- Map over all groupds. Fold over answers of persons with union/intersect
-- Count combined answers. Sum over groups
solve f = sum . map (length foldl1 f)
solve1 = solve union
solve2 = solve intersect
Much more understandable I would say. If you are also doing AoC, please go over your solution in the comments. See you tomorrow or you can go back to Day 1 for the series.