I may not be the most qualified, but I’m having a lot of F#un with Advent of Code 2024 (AOC)! It’s incredible how F# enables you to focus on problem-solving, making the experience even more enjoyable.
I had heard about AOC in the past but always dismissed it, thinking I was too busy and should prioritize solving “real-world” problems. However, tackling these challenges has proven to be a great learning experience—and, as it turns out, quite addictive once you earn that first gold star! ⭐
The first thing that stands out is how easy it is to dive in and start solving puzzles with F#. Unlike other languages where you might need to set up complex project structures, F# lets you just start coding.
What You Need:
• An editor like Visual Studio Code
• The .NET SDK
• The Ionide F# extension for VS Code
With this setup, you can simply create an F# script (.fsx file) and start coding immediately—no need for projects, solutions, compiled apps, or even tests (oops! 😆).
Day 1 – Part 1 Solution
Here’s my solution for Day 1, Part 1 using F#:
#load "utils.fsx"
open Utils
// utility functions
let parseLine (line: string) =
line.Split(" ")
|> Array.map int
|> function
| [| a; b |] -> a, b
| _ -> failwith "Invalid input"
// test lists
let list1 = [ 3; 4; 2; 1; 3; 3 ]
let list2 = [ 4; 3; 5; 3; 9; 3 ]
// solution
let calcDist list1 list2 =
let list1 = list1 |> Seq.sort
let list2 = list2 |> Seq.sort
// calculate the absolute difference between each pair of elements
// and sum them up
Seq.zip list1 list2
|> Seq.map (fun (a, b) -> abs (a - b))
|> Seq.sum
// printing the results
printfn $"Test lists: %d{calcDist list1 list2}"
readLines "input-day1.txt"
|> Array.map parseLine
|> Array.unzip
|> fun (list1, list2) -> calcDist list1 list2
|> printfn "Distance: %d"
Observations:
• Minimal boilerplate – F# allows you to express logic succinctly.
• Easy modularization – Other script files (utils.fsx) can be loaded just like modules, making it easy to reuse and share code.
Day 1 – Part 2 Solution
The second part of the puzzle turned out to be relatively straightforward as well:
let calcSim (list1: int seq) (list2: int seq) =
list1
|> Seq.map (fun x ->
// count the number of times x appears in list2
let c =
list2
|> Seq.countBy ((=) x)
|> Seq.filter (fst)
|> Seq.sumBy snd
// multiply x by the count
c * x)
|> Seq.sum
Final Thoughts
Without any unnecessary complexity or ceremony, F# proves to be a powerful and F#un language for solving Advent of Code puzzles. The combination of functional programming, immutability, and concise syntax makes tackling these challenges not only efficient but also enjoyable.