It's that time of the year again! Advent of Code is here! And although it is only 12 days instead of 25 this year, I am super excited as usual. Maybe I'll even be able to finish it this time!
This year, I'm going to try to solve the problems using F#. I have done a little bit of OCaml before, which is pretty similar, but have never used F#. Since I've been using a lot of C# at work, I figured I would try the functional language in the .NET world.
(To anyone who follows me because I used to write a lot about JavaScript, sorry to spam you with random languages... If you are interested in polyglot content with inconsistent publishing schedules and level of effort, then stay tuned :P)
Anyway, back to the problem at hand. I think day 1 was was a touch harder than previous years. It took me over an hour to finish both parts, but most of that was getting to know F# (and my new setup with MacOS + Zed + Arc).
I tried to use the strong points of F# to model the domain. Active Patterns will probably be useful for parsing later on, but they seemed redundant when I tried to use them today. I used a union type for the Left and Right rotations, but looking back, the problem would have been so much easier if I had just replaced all instances of "L" with "-1" and removed all instances of "R".
Part 1 was fairly straightforward with some modular arithmetic. Part 2 was a bit of a twist (there is a pun in there somewhere). I think my solution of multiplying the new_state with the old state to see if it crossed 0 was pretty clever, but maybe there is a better way I didn't think of.
Some quick thoughts on F# so far:
- Objects like
System.Stringare shared with other .NET languages, and therefore have the same methods. Collections are not shared and follow the pattern that most functional languages use with a module of helper functions. It is weird to see that mix of patterns in the code. - Compile errors have not been very friendly so far. Perhaps it is because of the nature of type inference. I have had similar issues with OCaml and Julia.
- Documentation seems to be split between
fsharp.organdlearn.microsoft.com. It has been a little confusing to figure out where to look.
open System
open System.IO
let input_string = File.ReadAllLines("input")
type Rotation =
| Left of int
| Right of int
let parse_input (input: string array) =
input
|> Array.filter (fun line -> line.Length > 0)
|> Array.map (fun line ->
if line.StartsWith "L" then Left (int (line.Trim('L')))
else Right (int (line.Trim('R'))))
let input = parse_input input_string
let part1 (input: Rotation array) =
input |> Array.fold (fun (sum, state) rotation ->
let new_state =
match rotation with
| Left l -> (state - l) % 100
| Right r -> (state + r) % 100
if new_state = 0 then (sum + 1, new_state) else (sum, new_state)
) (0, 50)
|> fst
printfn "%A" (part1 input)
let part2 (input: Rotation array) =
input |> Array.fold (fun (sum, state) rotation ->
let new_state =
match rotation with
| Left l -> state - l
| Right r -> state + r
if new_state = 0 then (sum + 1, new_state)
elif new_state * state < 0 then (Math.Abs(new_state) / 100 + 1 + sum, new_state % 100)
else (Math.Abs(new_state) / 100 + sum, new_state % 100)
) (0, 50)
|> fst
printfn "%A" (part2 input)
Top comments (0)