summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBrian Chu <brianmchu42@gmail.com>2022-01-09 11:38:26 -0800
committerBrian Chu <brianmchu42@gmail.com>2022-01-09 11:38:26 -0800
commit5f10a7c655aacbbc7f4f67607d758c65f196f436 (patch)
tree3ac50a3df96d0d108a7139b06ca513c20edb7dfc
parent50beae2167a705f694e4da4fa1ff63cfb1b2b16b (diff)
downloadAdventOfCode2016-5f10a7c655aacbbc7f4f67607d758c65f196f436.tar.gz
solution for day 21
-rw-r--r--day21.fsx88
1 files changed, 88 insertions, 0 deletions
diff --git a/day21.fsx b/day21.fsx
new file mode 100644
index 0000000..5d379be
--- /dev/null
+++ b/day21.fsx
@@ -0,0 +1,88 @@
+#r "nuget: FSHarpx.Collections, 3.0.1"
+open FSharpx.Collections
+open System.IO
+open System.Text.RegularExpressions
+
+let swapPos x y str =
+    str |> String.mapi (fun i v -> 
+                        match i with
+                        | _ when i = x -> str.[y]
+                        | _ when i = y -> str.[x]
+                        | _ -> v)
+
+
+let swapLetter x y str =
+    str |> String.mapi (fun i v -> 
+                        match v with
+                        | _ when v = x -> y
+                        | _ when v = y -> x
+                        | _ -> v)
+
+let rotateSteps steps dir (str: string) =
+    let steps = steps % str.Length
+    let  ls = str |> List.ofSeq |> if dir = "right" then List.rev else id
+    List.fold (fun (s, c) e -> if s <> 0 then (s-1 , List.append c.Tail [e]) else (0, c)) (steps, ls) ls
+    |> snd |> if dir = "right" then List.rev else id
+    |> List.map string 
+    |> String.concat ""
+
+let rotatePos (letter: char) (str: string) =
+    let index = str.IndexOf letter
+    rotateSteps (index + 1 + (if index >= 4 then 1 else 0)) "right" str
+
+let reversePos (x: int) (y: int) (str: string) =
+    let reversed = Seq.rev str[x..y] |> Seq.map string |> String.concat ""
+    (if x > 0 then str[..x-1] else "") + reversed + str[y+1..]
+
+let movePos (x: int) (y: int) (str:string) =
+    str |> Seq.mapi (fun i v ->
+                        match i with
+                        | _ when i = x -> ""
+                        | _ when i = y -> if x < y 
+                                          then (string v + string str[x]) 
+                                          else (string str[x] + string v)
+                        | _ -> string v)
+    |> String.concat ""
+
+let (|Regex|_|) pattern input = 
+    let m = Regex.Match(input, pattern)
+    if m.Success then Some(List.tail [for g in m.Groups -> g.Value])
+    else None
+
+let processLine (str: string): string -> string =
+    match str with
+    | Regex "swap position (\d) with position (\d)" [x; y] -> swapPos (int x) (int y)
+    | Regex "swap letter (\w) with letter (\w)" [x; y] -> swapLetter (char x) (char y)
+    | Regex "rotate (left|right) (\d) steps?" [dir; steps] -> rotateSteps (int steps) dir
+    | Regex "rotate based on position of letter (\w)" [letter] -> rotatePos (char letter)
+    | Regex "reverse positions (\d) through (\d)" [x; y] -> reversePos (int x) (int y)
+    | Regex "move position (\d) to position (\d)" [x; y] -> movePos (int x) (int y) 
+    | _ -> id
+
+// part 1
+let program = File.ReadAllLines "day21.txt" |> Array.map processLine |> Array.reduce (>>)
+let starter = "abcdefgh"
+program starter |> printfn "%s"
+
+// part 2
+let target = "fbgdceah" 
+let charsToString: char list -> string =
+    List.map string >> String.concat ""
+
+// permute all possible inputs to find which one yields the target
+let rec permute x =
+    let rec distribute e = function
+        | [] -> [[e]]
+        | x::xs' as xs -> (e::xs)::[for xs in distribute e xs' -> x::xs]
+
+    match x with
+    | [] -> [[]]
+    | e::xs -> List.collect (distribute e) (permute xs)
+
+starter 
+|> Seq.toList 
+|> permute 
+|> List.map charsToString
+|> List.map (fun x -> (x, program x))
+|> List.filter (snd >> ((=) target))
+|> printfn "%A"
\ No newline at end of file