The way I interpret this is. Given an input shaped like this;
abc
a
b
c
ab
ac
a
a
a
a
b
Where:
- Every line ending indicates a new 'user' (aoc jargon)
- Every double line ending indicates a new 'group' (aco jargon)
- And possible answers are
a...z
Count the amount of unique occurances for any given letter per group. I think we should be able to split by double empty lines, then groupBy character and count those groups.
Part one was quite straight forward. I'm contemplating moving to a Stack based setup as I'm unable to import modules for some reason...
My lack of importing Data.List.Split hasn't hold me back too much. I found my own cooked up string merger function was basically a groupBy in disquise. So I used that instead. Then, instead of merging them to strings, I merged them to lists. Then I transformed them to a list of the length and the actual strings (so I know how big the group would have to be). Then take the unique answers for that group, count all of the occurances and filter by the ones that have the specific group size. The length of those is the amount of answers that that group all answered.
While I got a bit stuck in the beginning trying to write my own function to split / merge lines. After I figured out I could rewrite that into a group / filter, things got clean quickly. I'm noticing I'm getting slightly more comfortable with the following;
- Apply infix operators prefix. So instead of doing
\x -> x == y
, you can also write(y ==)
. This is super nice. - Function composition. I'm already really familiar with this, but I noticed I wasn't really applying it here and just doing
map foo $ map bar $ map baz xs
instead of doingmap (foo . bar . baz) xs
. I should keep paying attention to this.
Browsing the subreddit I learned two things:
- If your fn looks like
fn xs = ... ... xs
, you can also writefn = ... ...
- Logically, that would return a function that takes somexs
. Makes complete sense! - Haskell has a function called
unions
andintersect
. Let's do some refactoring...