summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBrian Chu <brianmchu42@gmail.com>2022-02-19 11:14:27 -0800
committerBrian Chu <brianmchu42@gmail.com>2022-02-19 11:14:27 -0800
commite7614c20da8168140d0e34307f60474102d4541d (patch)
treede110e7c4e9ea92fb6e834d05072164ea21b0fe6
parentb5e8f96e5d6dedb6b55515a9dca8b70d9d3375ee (diff)
downloadAdventOfCode2017-e7614c20da8168140d0e34307f60474102d4541d.tar.gz
solution for day 16
-rw-r--r--day16.fsx60
1 files changed, 60 insertions, 0 deletions
diff --git a/day16.fsx b/day16.fsx
new file mode 100644
index 0000000..6b6de0c
--- /dev/null
+++ b/day16.fsx
@@ -0,0 +1,60 @@
+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"