open System.IO let keypad1 (pos: int * int): string = let (x, y) = pos string (x + 3 * y + 1) let keypad2 (pos: int * int): string = let pad = [ "--1--" "-234-" "56789" "-ABC-" "--D--" ] let (row, col) = pos string (pad[col][row]) let final_pos1 (start: int * int) (line: string) = let move (pos: int*int) (dPos: char) = let (x, y) = pos match dPos with | 'U' -> (x, y-1 |> max 0 |> min 2) | 'D' -> (x, y+1 |> max 0 |> min 2) | 'L' -> (x-1 |> max 0 |> min 2, y) | 'R' -> (x+1 |> max 0 |> min 2, y) | _ -> (-500, -500) List.fold move start (Seq.toList line) let final_pos2 (start: int*int) (line: string) = let move (pos: int*int) (dPos: char) = let (x, y) = pos let newPos = match dPos with | 'U' -> (x, y-1 |> max 0 |> min 4) | 'D' -> (x, y+1 |> max 0 |> min 4) | 'L' -> (x-1 |> max 0 |> min 4, y) | 'R' -> (x+1 |> max 0 |> min 4, y) | _ -> (-500, -500) if keypad2 newPos = "-" then pos else newPos List.fold move start (Seq.toList line) let lines = "day2.txt" |> File.ReadLines |> Seq.toList let generate_code (instructions: list) (posfunc: int*int -> string -> int*int) (keyfunc: int*int -> string) (start: int*int): list = let positions = List.scan posfunc start instructions List.map keyfunc positions[1..] // part 1 generate_code lines final_pos1 keypad1 (1, 1) |> String.concat "" |> printfn "%s" // part 2 generate_code lines final_pos2 keypad2 (0, 2) |> String.concat "" |> printfn "%s"