open System.IO type Reg = string type Lit = int type Value = | LiteralVal of literal: Lit | Register of register: Reg type Instruction = | Cpy of copied: Value * register: Reg | Inc of register: Reg | Dec of register: Reg | Jnz of compared: Value * offset: Lit let parseInstruction (line:string): Instruction = let split = line.Split " " match split[0] with | "inc" -> Inc split[1] | "dec" -> Dec split[1] | "cpy" -> let mutable parsed = 0 if (System.Int32.TryParse(split[1], &parsed)) then Cpy (LiteralVal parsed, split[2]) else Cpy (Register split[1], split[2]) | "jnz" -> let mutable parsed = 0 if (System.Int32.TryParse(split[1], &parsed)) then Jnz (LiteralVal parsed, (int split[2])) else Jnz (Register split[1], (int split[2])) | _ -> Inc "" let rec execute index insts registers = if index < 0 || index > (Array.length insts) - 1 then Map.find "a" registers else match insts[index] with | Cpy (value, reg) -> let copied = match value with | LiteralVal num -> num | Register reg -> Map.find reg registers let newRegisters = Map.change reg (function | Some x -> Some copied | None -> None) registers execute (index + 1) insts newRegisters | Inc reg -> let newRegisters = Map.change reg (function | Some x -> Some (x + 1) | None -> None) registers execute (index + 1) insts newRegisters | Dec reg -> let newRegisters = Map.change reg (function | Some x -> Some (x - 1) | None -> None) registers execute (index + 1) insts newRegisters | Jnz (reg, offset) -> let compared = match reg with | LiteralVal num -> num | Register reg -> Map.find reg registers if compared <> 0 then execute (index + offset) insts registers else execute (index + 1) insts registers let lines = File.ReadAllLines "day12.txt" |> Array.map parseInstruction let regsPart1: Map = Map.ofList [("a", 0); ("b", 0); ("c", 0); ("d", 0)] execute 0 lines regsPart1 |> printfn "%d" let regsPart2: Map = Map.ofList [("a", 0); ("b", 0); ("c", 1); ("d", 0)] execute 0 lines regsPart2 |> printfn "%d"