# Advent of Code Day 1–Easter Bunny HQ

- Posted in:
- Advent of Code
- F#

I’ve set up a GitHub repository for my F# solutions to Advent of Code this year, and although this year I suspect I won’t have enough time to blog about every day’s solution, I did attempt the first day’s problem.

As usual, the first part is simply parsing the problem input. For this problem, there was a string of directions like this: “L2, R3” which means turn left, go forward two blocks, turn right, go forward three blocks.

I needed to turn this into a sequence of “instructions”. Initially I used string splitting, and my instruction type encapsulated the change of direction and the number of blocks to move. But as it turned out, part 2 of the problem is more easily solved if there is a separate “turn” instruction, and instead of a “move forward n blocks” command, it should repeat the “move forward 1 block” command n times.

So by using a bit of regular expressions and a `Seq.collect`

to expand the move commands, we can get them into a sequence of `Instruction`

types like this:

open System.Text.RegularExpressions type Turn = Right | Left type Instruction = Turn of Turn | Move let input = System.IO.File.ReadAllText (__SOURCE_DIRECTORY__ + "\\input.txt") let instructions = Regex.Matches(input, "([LR])|(\\d+)") |> Seq.cast<Match> |> Seq.map (fun m -> m.Value) |> Seq.collect (function | "L" -> [Turn Left] | "R" -> [Turn Right] | n -> [for _ in 1..int(n) -> Move])

Now the state we need to maintain as we apply these commands is what our current position is, what direction we are facing, and (for part b of the problem), all the places we have visited so far.

This can be done by using a tuple for the current position, a vector indicating the direction we are facing (which eliminates some clumsy match statements from my original solution which created a discriminated union of `North | West | South | East`

), and an immutable set of all locations we have visited so far. Here’s my `State`

type and the starting state:

type State = { pos: int*int; facing: int*int; visited: Set<int*int> } let startState = { pos = (0,0); facing = (0,-1); visited = Set.empty }

Now we need a `move`

function that takes an instruction and a current state, and applies it, creating a new state. The instructions are either turn, or move one step forwards. So I created a couple of helper functions – one to rotate the direction, and one to add two vectors, and used them to implement the `move`

function:

let rotate (x,y) = function | Right -> (y*(-1),x) | Left -> (y,x*(-1)) let move state instruction = match instruction with | Turn direction -> { state with facing = rotate state.facing direction } | Move -> let addv (x,y) (i,j) = (x+i,y+j) { state with pos = addv state.pos state.facing; visited = Set.add state.pos state.visited }

Once we can apply one instruction, it is trivial to apply all the instructions with a `fold`

, and get the finishing state from which we only need the current position to solve part a:

let endState = instructions |> Seq.fold move startState let getDistance (x,y) = abs(x) + abs(y) printfn "Part a: Distance from home is %d" (getDistance endState.pos)

Part b required us to remember all the places we had been (which is why we maintain the `visited`

set in the state object), and identify the first place we visit twice. We can achieve this by using a `scan`

, which produces a sequence of states as we apply each instruction. That means we can use `find`

to iterate through until we find the first one where the current position is in the list of already visited places.

let visitedTwice = instructions |> Seq.scan move startState |> Seq.find (fun f -> f.visited.Contains(f.pos)) printfn "Part b: Distance from home is %d" (getDistance visitedTwice.pos)

You can see the full code here, and as always I welcome ideas about how my F# can be improved.

One of the interesting things about solving this challenge in F# was the realisation that I would have been able to solve it much quicker with procedural instead of functional code. I’d simply create a for loop to go through each instruction, mutating a current position and facing direction variable and adding positions to an already visited list.

By contrast, the functional solution was harder to refactor from part a to part b, since the `fold`

function I’d used wasn’t appropriate any more, and I had to significantly change my code to suit it to solving both halves of the problem.

So although I believe a functional paradigm has a lot of benefits over procedural, this challenge highlights that my brain is still wired to think procedurally, and it will be a while yet before I find the functional approach comes more naturally.