Today’s Advent of Code challenge had some similarities to yesterday’s. We have a series of “instructions”, which we need to apply one by one, and intermediate states are important. We’re also dealing with coordinates again so `int*int` tuples are the obvious choice.

For this problem, we essentially can use `fold` to apply each line of instructions and end up at the digit to be pressed, and then use `scan` to apply each line at a time, keeping track of our current position.

Something I am slowly getting the hang of is that in F# we can declare `let` bindings within `let` bindings. So within the `solve` function I declare a `lookup` function which the `isValid` function uses, which the `followInstruction` function uses which the `followLine` function uses. The `followInstruction` function itself also declares some helper functions that it needs.

By scoping functions to just where they are needed, we make it very obvious that these are single-use helper functions, which makes our code more understandable. They can of course be moved elsewhere if it turns out they are more generally applicable.

Here’s my code (also available on GitHub), and as always, I welcome suggestions for improvement

``````let solve (keypad:string[]) startPos input =
let isValid pos = lookup pos <> ' '
let followInstruction pos instruction =
let addv (x,y) (i,j) = x+i,y+j
let move = match instruction with | 'U' -> (0,-1) | 'D' -> (0,1) | 'R' -> (1,0) | 'L' -> (-1,0) | _ -> (0,0)
let newPos = addv pos move
if isValid newPos then newPos else pos
let followLine = Seq.fold followInstruction
input
|> Seq.scan followLine startPos
|> Seq.skip 1
|> Seq.map (lookup >> string)
|> System.String.Concat
|> printfn "Code: %s"

let keypadA = [| "     "; " 123 "; " 456 "; " 789 "; "     " |]
let keypadB = [| "       "; "   1   "; "  234  "; " 56789 "; "  ABC  "; "   D   "; "       " |]

let testInput = [| "ULL  "; "RRDDD"; "LURDL";  "UUUUD" |]
let input = System.IO.File.ReadAllLines (__SOURCE_DIRECTORY__ + "\\input.txt")