namespace Solutions module Day5 = open System.IO open System.Text.RegularExpressions // forgive me lord for what i'm about to do // too lazy to figure out how to parse initial state so hardcoding instead let initState = [| ['D'; 'T'; 'W'; 'N'; 'L']; ['H'; 'P'; 'C']; ['J'; 'M'; 'G'; 'D'; 'N'; 'H'; 'P'; 'W']; ['L'; 'Q'; 'T'; 'N'; 'S'; 'W'; 'C']; ['N'; 'C'; 'H'; 'P']; ['B'; 'Q'; 'W'; 'M'; 'D'; 'N'; 'H'; 'T']; ['L'; 'S'; 'G'; 'J'; 'R'; 'B'; 'M']; ['T'; 'R'; 'B'; 'V'; 'G'; 'W'; 'N'; 'Z']; ['L'; 'P'; 'N'; 'D'; 'G'; 'W'] |] type instruction = { amount: int; source: int; target: int } let getInstruction inst = let matches = Regex.Matches(inst, "move (\d+) from (\d+) to (\d+)") |> Seq.head |> fun x -> x.Groups |> List.ofSeq |> List.tail |> List.map (fun x -> int x.Value) assert (List.length matches = 3) {amount = matches[0]; source = matches[1] - 1; target = matches[2] - 1} let instructions = File.ReadLines("inputs/day5.txt") |> Array.ofSeq |> fun x -> Array.splitAt (Array.findIndex ((=) "") x) x |> snd |> Array.tail |> Array.map getInstruction let executeInstruction1 (state: list[]) inst = for _ in 1..inst.amount do match state[inst.source] with | top::bottom -> state[inst.source] <- bottom state[inst.target] <- top::state[inst.target] | _ -> failwith "this shouldn't happen" let part1 () = let mutable currentState = initState Array.iter (executeInstruction1 currentState) instructions Array.map (List.head >> string) currentState |> String.concat "" let executeInstruction2 (state: char [] []) inst = state[inst.target] <- Array.append state[inst.source].[..inst.amount-1] state[inst.target] state[inst.source] <- state[inst.source][inst.amount..] let part2 () = let mutable currentState = initState |> Array.map Array.ofList Array.iter (executeInstruction2 currentState) instructions Array.map (Array.head >> string) currentState |> String.concat ""