Advent of Code 2024 in F# - Day 1
Date: 2024-12-01 | create | build | fsharp | advent-of-code |
In this post we'll walk through solving Advent of Code 2024 Problem 1 using F#.
Full project source code is available to HAMINIONs members.
Part 1
Full Prompt: https://adventofcode.com/2024/day/1
My takeaways:
(*
Given:
* List of locationIds
* Left list
* Right list
Ask:
* Match up the locationId ordinalities (like 0th w 0th, 1st with 1st)
* Find the differences between these
* Sum the differences
Solutions:
* A: Simple order by and sum - O(nlogn + 2n), 2n
* Parse out all values from left, right - O(n), n
* Sort each ascending - O(nlogn), n
* Parse over sorted lists and sum - O(n)
*)
Solution code:
let solve: unit -> int = fun () ->
printfn "Problem 1.1: Solving"
let exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
let filePath = Path.Combine(exeDir, "Static", "problem_1_input.txt")
let lines = File.ReadLines(filePath)
printfn "Problem 1.1: Found %A locations" (Seq.length lines)
let left_list, right_list =
lines
|> Seq.map(fun l ->
let left_and_right =
l.Split(" ")
|> Array.filter (fun s -> not (String.IsNullOrWhiteSpace s))
assert (left_and_right.Length = 2)
(left_and_right[0], left_and_right[1])
)
|> List.ofSeq
|> List.unzip
let left_list_sorted =
List.sort left_list
let right_list_sorted =
List.sort right_list
assert (left_list_sorted.Length = right_list_sorted.Length)
let mutable total_difference = 0
seq { 0..(left_list_sorted.Length - 1) }
|> Seq.iter (fun index ->
let left_value = int left_list_sorted[index]
let right_value = int right_list_sorted[index]
let difference = abs (right_value - left_value)
total_difference <- total_difference + difference
)
printfn "Problem 1.1: Total Difference = %A" total_difference
total_difference
My answer: 2430334
Part 2
Full Prompt: https://adventofcode.com/2024/day/1
My takeaways:
(*
Given:
* List of location Ids
Ask:
* Calculate similarity score - add up number in left list after multiplying by number of times appears in right list
Solution:
* A: Calculate frequency in right list, sum from left
* Calculate right frequency - iterate over values keeping freq dict - O(n), n
* Iterate over left values - O(n)
* if not in frequency -> 0
* else val * frequency
*)
Solution:
let solve_part2 = fun () ->
printfn "Problem 1.2: Solving"
let exeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
let filePath = Path.Combine(exeDir, "Static", "problem_1_input.txt")
let lines = File.ReadLines(filePath)
printfn "Problem 1.2: Found %A locations" (Seq.length lines)
let left_list, right_list =
lines
|> Seq.map(fun l ->
let left_and_right =
l.Split(" ")
|> Array.filter (fun s -> not (String.IsNullOrWhiteSpace s))
assert (left_and_right.Length = 2)
(left_and_right[0], left_and_right[1])
)
|> List.ofSeq
|> List.unzip
let right_list_id_to_frequency_lookup =
right_list
|> Seq.countBy id
|> dict
let total_value =
Seq.fold
(fun acc left_id ->
let multiplier =
match right_list_id_to_frequency_lookup.TryGetValue left_id with
| true, frequency -> frequency
| false, _ -> 0
acc + ((int left_id) * multiplier))
0
left_list
printfn "Problem 1.2: Total Value: %A" total_value
My answer: 28786472
Next
Overall this one wasn't so hard but I got to try out some F# built-ins that I hadn't touched before - namely countBy, unzip, and fold.
I'm going to try to keep up with AOC this year and I'll be posting my full code and answers here and in my example project repo.
If you want the full project source code or a reference for how to setup a simple F# boilerplate - join HAMINIONs to get full access.
If you liked this post you might also like:
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.