Advent of Code Day 2–Bathroom Code
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 lookup (x,y) = keypad.[y].[x]
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")
solve keypadA (2,2) testInput
solve keypadA (2,2) input // part a
solve keypadB (3,3) input // part b