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.