diff options
Diffstat (limited to 'aoc-2022-dotnet/Day05/Program.fs')
-rw-r--r-- | aoc-2022-dotnet/Day05/Program.fs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/aoc-2022-dotnet/Day05/Program.fs b/aoc-2022-dotnet/Day05/Program.fs new file mode 100644 index 0000000..e15f53d --- /dev/null +++ b/aoc-2022-dotnet/Day05/Program.fs @@ -0,0 +1,67 @@ +open System +open System.IO +open FParsec + +type Move = + | Move of int * int * int + + static member parse str = + let dec n = n - 1 + let pPart str = pstring str >>. pint32 + let pMove = tuple3 (pPart "move ") (pPart " from " |>> dec) (pPart " to " |>> dec) + + match run pMove str with + | Success (result, _, _) -> Move result + | _ -> failwith "Invalid move format!" + + static member execute order stacks (Move (n, fi, ti)) = + List.mapi + (fun i x -> + if i = fi then + List.item fi stacks |> List.skip n + elif i = ti then + (List.item fi stacks |> List.take n |> order) + @ List.item ti stacks + else + x) + stacks + +let parseStacks str = + let pFullCrate = pchar '[' >>. anyChar .>> pchar ']' |>> Some + let pEmptyCrate = pstring " " >>% None + let pCrate = pFullCrate <|> pEmptyCrate + let pCrateLine = sepBy pCrate (pchar ' ') .>> skipNewline + let pHeader = many pCrateLine + + let parsed = + match run pHeader str with + | Success (result, _, _) -> result + | _ -> failwith "Invalid header format!" + + parsed + |> List.transpose + |> List.map (List.choose id) + +let solve order input = + let headerList = + input + |> Seq.takeWhile (not << String.IsNullOrEmpty) + |> Seq.toList + + let stacks = parseStacks <| String.Join("\n", headerList) + + String.Concat( + input + |> Seq.skip (headerList.Length + 1) + |> Seq.map Move.parse + |> Seq.fold (Move.execute order) stacks + |> List.map List.head + ) + +let test = File.ReadLines "test.txt" +assert (solve List.rev test = "CMZ") +assert (solve id test = "MCD") + +let input = File.ReadLines "input.txt" +printfn "%s" <| solve List.rev input +printfn "%s" <| solve id input |