Haskelling the Advent of Code 2020 - Day 6
Dec 6, 2020 06:53 · 1069 words · 6 minute read
Hi Haskellings! For today’s retrospective i was looking at some of yesterday’s solutions in other languages and i noticed that a lot of those languages have a translate function which is able to translate using a mapping from certain strings to other strings and this would allow us to get rid of this bin function and we could just do the translate directly like that because it’s a String we’ll have to use digitToInt to convert the ‘0’ or ‘1’ character into an Int. Let’s write our tr function now and this function is going to take a [Char] but we’re going to make it generic so we’re going to say a [a] and another [a] and then it’s going to give us back a translation function which can convert a String to another string so which is again a [a] -> [a] we can call the lists that form our map xs and ys and then we’re going to use Data.Map and zip to create a Map from those two lists we can use fromList from Data.Map combined with zip of xs and ys to create our Map once we have the Map we then need to map across the lookup (M.!) function to create our translating function so we M.
! on that list each of the elements in turn from the String we’re given to translate 01:53 - digitToInt comes from Data.Char so we just import that and another problem is that Data.Map requires the index to have typeclass Ord so we add that type constraint and we have ourselves a nice tr function this fold function is also a nice generic function which we can call readBin and we have ourselves two functions which we can reuse in other places so we can actually put those functions into our Advent of Code module and we have ourselves then a nice one liner at the end okay so let’s do that let’s put those functions into our Advent of Code module and we put the import with the other imports Data.Char is already there and then we put those two functions just at the bottom of the file there let’s also add Data.List and Data.Char to our exporting modules this means that we don’t need to import those if we use functions from those modules in our other solutions we still have a problem because readBin needs a type signature so let’s just add one in okay it seems that Data.List and Text.
Parsec both export uncons so let’s hide the one from Parsec 03:28 - and now we should actually have a nice one liner in our solution file just like the other languages! :-) let’s move on to day 6 and as you can see we have input data once again that’s in groups separated by blank lines first we’re going to fetch our input data and we have a quick look at it just like the example it’s in groups split by blank lines so we’re going to use the Data.List.Split module and specifically a function called splitOn in that module and we’re going to split on blank lines like this once again this is the interact function from our AOC library not the Prelude interact so we have our [[String]] here so each of those [String] is one of the groups all we have to do is actually concatenate those together and then use the Data.Set library to ensure that we have only one of each letter in each group this will essentially combine the questionnaires of the groups in such a way that we see only one of the letters for each group so we then just sum the sizes of those groups and we should have our answer let’s check that and indeed we have our first gold star the second part is quite similar only this time we need to find out how many questions everyone in the group answered “yes” to this means we’ll need to find the intersection across the group of those questions and in that case we’re going to need to have a set for each questionnaire and then get the intersection of each of those sets so we map the Data.Set.fromList function across each questionnaire then we intersect those together however the intersect function from Data.Set only operates between two sets so we’ll have to use fold again and once again we’ll use the foldl’ variant of fold and we fold across those sets using intersection however we have to use a different variant of fold because we don’t have an initial set and fortunately there is a foldl1’ function that allows us to use the head of the list as the initial accumulator now that we’ve done that we just again need to find the size of that resulting set and the sum of those should be our answer okay let’s try that and of course that works and we have our second gold star we’re going to jump straight into today’s retrospective and the only thing i can think that we might want to do is take out our splitOn function and make a new version of interact and we’re going to call this interactg and this is perhaps part of the problem of having a big library of functions is that that name is probably going to be difficult to remember in the future but let’s do this anyway so we essentially just removed the splitOn from each of these and we call our new interact function interactg so i think this split module is going to be quite useful to us at some stage so let’s add this to the exported module list we can then import that module to make sure that the names are in our namespace and then we create a new interact function and it’s simply just going to call interact on f.
splitOn [“”] 07:39 - the type signature of this function is going to be quite similar to our existing interact function except f is going to take a [[String]] because when we do the splitOn it creates a list of lists now we get a build error because Data.List.Split exports a few names that are also exported by our Parsec library but we can simply hide those names in our import of Data.List.Split This compiles nicely, so, until next time, happy Haskelling! .