summary refs log tree commit diff stats
path: root/day18.fsx
diff options
context:
space:
mode:
Diffstat (limited to 'day18.fsx')
-rw-r--r--day18.fsx86
1 files changed, 86 insertions, 0 deletions
diff --git a/day18.fsx b/day18.fsx
new file mode 100644
index 0000000..383519f
--- /dev/null
+++ b/day18.fsx
@@ -0,0 +1,86 @@
+open System.IO
+open System.Collections.Generic
+open System.Text.RegularExpressions
+
+type Register = string
+type Value =
+    | Literal of int64
+    | Reg of Register
+
+let (|InstRegex|_|) pattern string =
+    let m = Regex(pattern).Match(string)
+    if m.Success then
+        Some(List.tail [for g in m.Groups -> g.Value])
+    else None
+
+type Instruction =
+    | Snd of x: Value
+    | Set of x: Register * y: Value
+    | Add of x: Register * y: Value
+    | Mul of x: Register * y: Value
+    | Mod of x: Register * y: Value
+    | Rcv of x: Value
+    | Jgz of x: Value * y: Value
+
+let resolveValue (value: Value) (registers: Dictionary<string, int64> ) =
+    let tryGetDefaultRegister key =
+        if not (registers.ContainsKey(key)) then registers.[key] <- 0L
+        registers.[key]
+ 
+    match value with
+    | Literal x -> x
+    | Reg x -> tryGetDefaultRegister x
+
+let parseValue line =
+    match line with
+    | InstRegex "snd ([a-p])" [x]              -> Snd (Reg x)
+    | InstRegex "snd (-?\d+)" [x]              -> Snd (Literal (int x))
+    | InstRegex "set ([a-p]) ([a-p])" [x; y]   -> Set (x, Reg y)
+    | InstRegex "set ([a-p]) (-?\d+)" [x; y]   -> Set (x, Literal (int y))
+    | InstRegex "add ([a-p]) ([a-p])" [x; y]   -> Add (x, Reg y)
+    | InstRegex "add ([a-p]) (-?\d+)" [x; y]   -> Add (x, Literal (int y))
+    | InstRegex "mul ([a-p]) ([a-p])" [x; y]   -> Mul (x, Reg y)
+    | InstRegex "mul ([a-p]) (-?\d+)" [x; y]   -> Mul (x, Literal (int y))
+    | InstRegex "mod ([a-p]) ([a-p])" [x; y]   -> Mod (x, Reg y)
+    | InstRegex "mod ([a-p]) (-?\d+)" [x; y]   -> Mod (x, Literal (int y))
+    | InstRegex "rcv ([a-p])" [x]              -> Rcv (Reg x)
+    | InstRegex "rcv (-?\d+)" [x]              -> Rcv (Literal (int x))
+    | InstRegex "jgz ([a-p]) ([a-p])" [x; y]   -> Jgz (Reg x, Reg y)
+    | InstRegex "jgz ([a-p]) (-?\d+)" [x; y]   -> Jgz (Reg x, Literal (int y))
+    | InstRegex "jgz (-?\d+) ([a-p])" [x; y]   -> Jgz (Literal (int x), Reg y)
+    | InstRegex "jgz (-?\d+) (-?\d+)" [x; y]   -> Jgz (Literal (int x), Literal (int y))
+    | x -> printfn "%A" x; failwith "invalid input"
+
+let rec executeInst (instructions: Instruction array) registers (index: int64) lastSound =
+    match instructions.[int index] with
+    | Snd x -> 
+        executeInst instructions registers (index + 1L) (resolveValue x registers)
+    | Set(x, y) -> 
+        if not (registers.ContainsKey(x)) then registers.[x] <- 0
+        registers.[x] <- resolveValue y registers
+        executeInst instructions registers (index + 1L) lastSound
+    | Add(x, y) ->
+        if not (registers.ContainsKey(x)) then registers.[x] <- 0
+        registers.[x] <- registers.[x] + resolveValue y registers
+        executeInst instructions registers (index + 1L) lastSound
+    | Mul(x, y) -> 
+        if not (registers.ContainsKey(x)) then registers.[x] <- 0
+        registers.[x] <- registers.[x] * resolveValue y registers
+        executeInst instructions registers (index + 1L) lastSound
+    | Mod(x, y) -> 
+        if not (registers.ContainsKey(x)) then registers.[x] <- 0
+        registers.[x] <- registers.[x] % resolveValue y registers
+        executeInst instructions registers (index + 1L) lastSound
+    | Rcv x -> 
+        if (resolveValue x registers) > 0 then lastSound else executeInst instructions registers (index + 1L) lastSound
+    | Jgz(x, y) ->
+        if (resolveValue x registers) > 0 then
+            executeInst instructions registers (index + resolveValue y registers) lastSound
+        else
+            executeInst instructions registers (index + 1L) lastSound
+
+let () =
+    let registers = new Dictionary<string, int64>()
+    let input = File.ReadAllLines "day18.txt" |> Array.map parseValue
+    let recovered = executeInst input registers 0 0
+    printfn "%A" recovered
\ No newline at end of file