blob: 6b6de0cb680f1460e8eb0c3ee7b5cf9c3d8b7d0d (
plain) (
tree)
|
|
open System.IO
open System.Text.RegularExpressions
type Move =
| Spin of offset: int
| Exchange of first: int * second: int
| Partner of first: char * second: char
let (|MoveRegex|_|) pattern input=
let m = Regex(pattern).Match(input)
if m.Success then Some(List.tail [for x in m.Groups -> x.Value])
else None
let parseMove str =
match str with
| MoveRegex "s(\d+)" [x] -> Spin(int x)
| MoveRegex "x(\d+)/(\d+)" [x; y] -> Exchange(int x, int y)
| MoveRegex "p(\w)/(\w)" [x; y] -> Partner(char x, char y)
| _ -> failwith "invalid input"
let swapPos x y (chars: char array) =
chars |> Array.mapi (fun i v ->
match i with
| _ when i = x -> chars.[y]
| _ when i = y -> chars.[x]
| _ -> v)
let swapLetter x y (chars: char array) =
let indexOf elem = chars |> Array.findIndex((=) elem)
swapPos (indexOf x) (indexOf y) chars
let spinChars steps (str: char array) =
let startIndex = str.Length - steps
let first, last = str[..startIndex - 1], str[startIndex..]
Array.append last first
let executeMove chars move =
match move with
| Spin x -> spinChars x chars
| Exchange (x, y) -> swapPos x y chars
| Partner (x, y) -> swapLetter x y chars
let rec executeMoves state moves seen =
let newState = Array.fold executeMove state moves
if List.contains newState seen then
let r = List.rev seen
let l = List.length seen
let m = 1000000000 % l
r.[m]
else
executeMoves newState moves (newState :: seen)
let () =
let moves = (File.ReadAllText "day16.txt").Trim().Split(',') |> Array.map parseMove
let initialState = ("abcdefghijklmnop" |> Array.ofSeq)
let finalState = Array.fold executeMove initialState moves
// part 1
finalState |> Array.map string |> String.concat "" |> printfn "%s"
// part 2
executeMoves initialState moves [initialState] |> Array.map string |> String.concat "" |> printfn "%s"
|