diff options
-rw-r--r-- | day23.fsx | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/day23.fsx b/day23.fsx new file mode 100644 index 0000000..3378516 --- /dev/null +++ b/day23.fsx @@ -0,0 +1,115 @@ +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: Value + | Tgl of offset: Value + | Nop + +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 parsed1 = 0 + if (System.Int32.TryParse(split[1], &parsed1)) + then + let mutable parsed2 = 0 + if (System.Int32.TryParse(split[2], &parsed2)) + then Jnz (LiteralVal parsed1, LiteralVal parsed2) + else Jnz (LiteralVal parsed1, Register split[2]) + else + let mutable parsed2 = 0 + if (System.Int32.TryParse(split[2], &parsed2)) + then Jnz (Register split[1], LiteralVal parsed2) + else Jnz (Register split[1], Register split[2]) + | "tgl" -> + let mutable parsed = 0 + if (System.Int32.TryParse(split[1], &parsed)) + then Tgl (LiteralVal parsed) + else Tgl (Register split[1]) + | _ -> Inc "" + +let toggleInst (inst: Instruction) : Instruction = + match inst with + | Inc reg -> Dec reg + | Dec reg -> Inc reg + | Tgl offset -> + match offset with + | LiteralVal v-> Nop + | Register r -> Inc r + | Cpy (copied, register) -> Jnz (copied, Register register) + | Jnz (compared, offset) -> + match offset with + | LiteralVal v-> Nop + | Register r -> Cpy (compared, r) + | Nop -> Nop + +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 offset = + match offset with + | LiteralVal x -> x + | Register x -> Map.find x registers + 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 + | Tgl offset -> + let offset = + match offset with + | LiteralVal x -> x + | Register x -> Map.find x registers + let newIndex = index + offset + let newInsts = Array.mapi (fun i v -> + match i with + | _ when i = newIndex -> toggleInst v + | _ -> v) insts + execute (index + 1) newInsts registers + | Nop -> + execute (index + 1) insts registers + + +let lines = File.ReadAllLines "day23.txt" |> Array.map parseInstruction +let regsPart1: Map<string, Lit> = Map.ofList [("a", 7); ("b", 0); ("c", 0); ("d", 0)] +execute 0 lines regsPart1 |> printfn "%d" +// analysis of the code indicates it actually calculates reg[a]! + some constant derived from the code +// in this case, the constant is 90 * 81 +// thus part 2 is 90 * 81 + 12! = 479008890 \ No newline at end of file |