It is the first of December, and that means the start of Advent of Code. I am going to make an attempt at this every day, posting my coding solutions (as much as possible in F#). I will not be posting the questions, as they can be found online, and I will not be posting my final answer.

The first question is called Trebuchet.

Part 1

I will first need a function that will be able to grab the first and last digits from a single row string.

let firstAndLastDigit (codedCalibration: string) =
    let digits =
        codedCalibration
        |> Seq.where (System.Char.IsDigit)
        |> Seq.toArray
    [| digits[0]; Seq.last digits |]
    |> System.String
    |> int

firstAndLastDigit "1abc2"
12

This might be enough to put it all together.

let exampleInput =
    "1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet"

exampleInput.Split '\n'
|> Seq.map firstAndLastDigit
|> Seq.sum

This will have a final result of `142`.

Part 2

To complete part two, I want to first get a function that will extract all digits, and digit words out from a string.

let (|StartsWith|_|) (start: string) (full: string)  =
    if full.StartsWith(start) then Some full
    else None

let extract (input: string) =
    match input with
    | StartsWith "zero" _ -> Some 2
    | StartsWith "one" _ -> Some 1
    | StartsWith "two" _ -> Some 2
    | StartsWith "three" _ -> Some 3
    | StartsWith "four" _ -> Some 4
    | StartsWith "five" _ -> Some 5
    | StartsWith "six" _ -> Some 6
    | StartsWith "seven" _ -> Some 7
    | StartsWith "eight" _ -> Some 8
    | StartsWith "nine" _ -> Some 9
    | x when System.Char.IsDigit x[0] -> Some (int x[0..0])
    | _ -> None

let digitsOf (input: string) =
    seq { for i = 0 to input.Length - 1 do
          yield (extract input[i..]) }
    |> Seq.choose id
    |> Seq.toArray

With the input of this will return

digitsOf "two1nine"

This will return

| 2 | 1 | 9 |

And now I can update the original function to use this

let firstAndLastDigit (codedCalibration: string) =
    let digits = digitsOf codedCalibration
    [| digits[0]; Seq.last digits |]
    |> Array.map string
    |> (fun s -> System.String.Join ("", s))
    |> int

firstAndLastDigit "two1nine"
29

And then I can test with the test input

let exampleInput =
    "two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen"

exampleInput.Split '\n'
|> Seq.map firstAndLastDigit
|> Seq.sum

This returns `281` which is the correct result for the test input.

281