Advent of Code F# – Day 1 to 6

You can become a serverless blackbelt. Enrol to my 4-week online workshop Production-Ready Serverless and gain hands-on experience building something from scratch using serverless technologies. At the end of the workshop, you should have a broader view of the challenges you will face as your serverless architecture matures and expands. You should also have a firm grasp on when serverless is a good fit for your system as well as common pitfalls you need to avoid. Sign up now and get 15% discount with the code yanprs15!

In case you missed it, a lot of the good folks in the F# community has been doing the Advent of Code the past 2 weeks. I’m a bit late to the game, but have done a lot of catching up this weekend, and here’s my solutions for the day 1-6.

p.s. you can find all my solution on github, but the input is different for everyone.


Day 1


Starting off nice and simple, we can solve this problem with a fold.


The only caveat I encountered with this problem was in fact, trying to capture the input into a string value:


which for some reason seems to upset F# interactive:


Which is why I defined the input in a source file (day01.fs) whilst keeping the actual solution in the script (day01.fsx).

After you solve the question, the second part of the challenge is revealed (the same theme runs throughout all the challenges).


Day 1 (Part 2)


This requires a slight twist to our approach to part 1 – we need the intermediate steps of the fold instead of the final value.

Fortunately Seq.scan does just that!


Another thing to note is that, since Seq.scan returns the initial value (0 in this case) as part of the returned sequence, it means we didn’t have to shift our index system from 0-based to 1-based.


Day 2


First, bear in mind that the input looks like this:


so let’s add a helper to make splitting strings easier (and prettier):




Day 2 (Part 2)


To find the shortest distance around the smallest side, we just have to sort the dimensions then pick the first 2. So our solution only needs a small tweak from part 1:



Day 3


Starting with an implied position of (0, 0), in order to find the number of houses that received at least one present we need to find the number of distinct positions that Santa has traversed.

Again, fold to the rescue!



Day 3 (Part 2)


First, let’s extract our fold logic out from part 1:


Now, we need to massage the input (e.g. ^v^v^v^v^v) into two sequences, i.e.:

input : seq { ‘^’; ‘v’; ‘^’; ‘v’; ‘^’; ‘v’; ‘^’; ‘v’; ‘^’; ‘v’ }

we want :

seq {

seq { ‘^’; ‘^’; ‘^’; ‘^’; ‘^’ }  // for Santa

seq { ‘v’; ‘v’; ‘v’; ‘v’; ‘v’ }   // for Robot-Santa


which is what the first 4 LOC does:


so, to explain, we start with “^v^v^v^v” which is really just a sequence of chars:

seq { ‘^’; ‘v’; ‘^’; ‘v’; ‘^’; ‘v’; ‘^’; ‘v’; ‘^’; ‘v’ }

=> seq { (0, ‘^’); (1, ‘v’); (0, ‘^’); (1, ‘v’); … }

=> seq {

(0, seq { (0, ‘^’); (0, ‘^’); (0, ‘^’); … })

(1, seq { (1, ‘v’); (1, ‘v’); (1, ‘v’); … }) }

=> seq {

seq { ‘^’; ‘^’; ‘^’; … }

seq { ‘v’; ‘v’; ‘v’; … } }

after we’ve done that, we

  1. apply the same fold logic we did previously against each of the inner sequences;
  2. collect the result (i.e. the positions traversed) into a unified sequence
  3. count the distinct positions traversed by both Santa and Robot-Santa

and job done!


Day 4


In .Net you can use System.Security.Cryptography.MD5 to create a MD5 hash (as a byte[]) for some input byte[].

You can then use BitConverter.ToString to get back a string representation of the hex-decimal value for the hash.

Or, you can take a shortcut, and take advantage of binary-to-hex conversion where every 4 bits = 1 hex value:



Day 4 (Part 2)


Because of the approach we took for part 1, the change here becomes as trivial as checking if the 3rd byte is also 0uy!



Day 5


First, let’s capture the three requirements for a nice string.

At least 3 vowels, check.


At least 1 letter that appear twice in a row, check.


Does not contain certain strings, check (in a more generic way).


Then, let’s create a helper to make it easier for us to compose these three requirements later:


and finally let’s put everything together:



aside : I think the <&&> operator makes the code easier to read here. I’m usually not a fan of special operators, I find they often gets in the way of discoverability and raises the barrier to entry for a library if there are too many special operators one has to remember. I think it’s ok in this case given that the scope is really small.


Day 5 (Part 2)


Again, let’s capture the 2 new requirements as functions.

At least one pair of letters that appear twice without overlap, check.


Here, I’m taking advantage of the fact that all the strings contains only alphabet characters and replacing the pair of characters currently being considered with ‘-’. However, it still feels as though I’m taking the scenic route to express the requirement here, if you have a better way, please let me know in the comments.

At least one letter that repeats with exactly one letter in between, check.


Like before, we just need to compose the two together to solve this challenge.



Day 6


First, let’s look at the input for this challenge.

turn on 489,959 through 759,964
turn off 820,516 through 871,914
turn off 427,423 through 929,502
toggle 756,965 through 812,992

so, we have coordinates – int, int – and three different actions – turn on, turn off, toggle – that we need to deal with:


For each line, the format is:

{action} {start_coordinate} through {end_coordinate}

so we can write a simple function to parse it:


After the first split, we’ll end up an array consisting of the two coordinates, e.g.

[| “ 489,959 ”; “ 759,964 ” |]

splitting each by ‘,’ again gives us an array of arrays, e.g.:

[|  [| “489”; “959” |];  [| “759”; “964” |]  |]

which is why we needed to further massage the inner arrays in to int tuples.

[| (489, 959); (759, 964) |]


Next, let’s have some lights!


And we also need a function to perform the parsed Action against the corresponding coordinate rages:


and then hook everything together:



Finally, let’s count how many of the lights are turned on after performing all the actions. Unfortunately, there’s no built-in sum, or sumBy functions in the Array2D module.. so for simplicity sake let’s just resort to using mutable state again.



Day 6 (Part 2)


We can reuse most of what we had done for part 1 of the challenge, the main thing that has to change is the perform function:


and also how we calculate the final result:


and that’s it!


From Day 7, the challenges start to get more challenging, so watch this space for more solutions to come.

Liked this article? Support me on Patreon and get direct help from me via a private Slack channel or 1-2-1 mentoring.
Subscribe to my newsletter

Hi, I’m Yan. I’m an AWS Serverless Hero and I help companies go faster for less by adopting serverless technologies successfully.

Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.

Hire me.

Skill up your serverless game with this hands-on workshop.

My 4-week Production-Ready Serverless online workshop is back!

This course takes you through building a production-ready serverless web application from testing, deployment, security, all the way through to observability. The motivation for this course is to give you hands-on experience building something with serverless technologies while giving you a broader view of the challenges you will face as the architecture matures and expands.

We will start at the basics and give you a firm introduction to Lambda and all the relevant concepts and service features (including the latest announcements in 2020). And then gradually ramping up and cover a wide array of topics such as API security, testing strategies, CI/CD, secret management, and operational best practices for monitoring and troubleshooting.

If you enrol now you can also get 15% OFF with the promo code “yanprs15”.

Enrol now and SAVE 15%.

Check out my new podcast Real-World Serverless where I talk with engineers who are building amazing things with serverless technologies and discuss the real-world use cases and challenges they face. If you’re interested in what people are actually doing with serverless and what it’s really like to be working with serverless day-to-day, then this is the podcast for you.

Check out my new course, Learn you some Lambda best practice for great good! In this course, you will learn best practices for working with AWS Lambda in terms of performance, cost, security, scalability, resilience and observability. We will also cover latest features from re:Invent 2019 such as Provisioned Concurrency and Lambda Destinations. Enrol now and start learning!

Check out my video course, Complete Guide to AWS Step Functions. In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. There is something for everyone from beginners to more advanced users looking for design patterns and best practices. Enrol now and start learning!