Essay - Published: 2024.12.03 | advent-of-code | build | create | fsharp |
DISCLOSURE: If you buy through affiliate links, I may earn a small commission. (disclosures)
In this post I'll share my solution to Advent of Code 2024 Day 3 using F#.
HAMINIONs Members get full access to the project files so you can git clone and run it yourself.
Prompt: https://adventofcode.com/2024/day/3
Given:
Ask:
mul(X,Y)
SubProblems:
mul( and end )Solutions:
Code:
let read_all_input_text: unit -> string = fun () ->
let exe_dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
let file_path = Path.Combine(exe_dir, "Static", "day_3_input.txt")
let all_text = File.ReadAllText(file_path)
all_text
let read_all_mul_values_from_input
(all_text: string)
: (int * int) list
=
let mul_regex_pattern = @"mul\((\d+),(\d+)\)"
let matches = Regex.Matches(all_text, mul_regex_pattern)
matches
|> Seq.map (fun m ->
let a = int m.Groups[1].Value
let b = int m.Groups[2].Value
(a, b)
)
|> Seq.toList
let solve_part1 = fun () ->
printfn "Day 3.1: Solving"
let total =
read_all_input_text()
|> read_all_mul_values_from_input
|> List.sumBy (fun t ->
let a, b = t
a * b
)
printfn "Day 3.1: Total: %A" total
My answer: 175015740 -> Accepted
Prompt: https://adventofcode.com/2024/day/3
Given:
Ask:
SubProblems:
Solutions:
Code:
let get_all_starting_indices
(all_text: string)
(regex_pattern: string)
: int list
=
Regex.Matches(all_text, regex_pattern)
|> Seq.map (fun m -> m.Index)
|> List.ofSeq
let get_enabled_input_sections
(all_text: string)
: string
=
let dont_string = @"don't\(\)"
let do_string = @"do\(\)"
let all_dont_indices =
get_all_starting_indices
all_text
dont_string
let all_do_indices =
get_all_starting_indices
all_text
do_string
(*
* Do section is do -> next don't
* Don't section is don't -> next do
Iteration:
* Sliding window - first do to first don't (or end)
*)
let first_dont_index = all_dont_indices[0]
let mutable do_index = 0
let mutable dont_index = 1
let mutable processed_string_index = first_dont_index
let mutable all_enabled_indices: (int * int) List = List<(int * int)>()
all_enabled_indices.Add((0, first_dont_index))
while do_index < all_do_indices.Length && dont_index < all_dont_indices.Length do
// Find next do
let mutable next_do_string_pointer = 0
while do_index < all_do_indices.Length && next_do_string_pointer <= processed_string_index do
next_do_string_pointer <- all_do_indices[do_index]
do_index <- do_index + 1
// Find next don't
let mutable next_dont_string_pointer = 0
while (dont_index < all_dont_indices.Length
&& (next_dont_string_pointer <= processed_string_index
|| next_dont_string_pointer <= next_do_string_pointer)) do
next_dont_string_pointer <- all_dont_indices[dont_index]
dont_index <- dont_index + 1
all_enabled_indices.Add((next_do_string_pointer, next_dont_string_pointer))
processed_string_index <- next_dont_string_pointer
// Catch case where we still have a do left
if do_index < all_do_indices.Length && dont_index >= all_do_indices.Length then
let mutable next_do_string_pointer = all_do_indices[do_index]
while do_index < all_do_indices.Length && next_do_string_pointer <= processed_string_index do
next_do_string_pointer <- all_do_indices[do_index]
do_index <- do_index + 1
if next_do_string_pointer > processed_string_index then
all_enabled_indices.Add((next_do_string_pointer, all_text.Length - 1))
all_enabled_indices
|> Seq.map (fun indices ->
let start, end_index = indices
all_text.[start..end_index]
)
|> String.concat ""
let solve_part2 = fun() ->
printfn "Day 3.2: Solving"
let total =
read_all_input_text()
|> get_enabled_input_sections
|> read_all_mul_values_from_input
|> List.sumBy (fun t ->
let a, b = t
a * b
)
printfn "Day 3.2: Total: %A" total
My Answer -> Accepted
Notes:
do() statementThis one was a little tricky and I don't love my solution to this but it works and sometimes you just have to be okay with that.
If you liked this post you might also like:
The best way to support my work is to like / comment / share for the algorithm and subscribe for future updates.