Supply Stacks
Description: https://adventofcode.com/2022/day/5
open System.IO
open System
open System.Text.RegularExpressions
type Ship(numberOfStacks: int, isCrateMover9001: bool) =
let commandPattern = Regex(@"move (?<number>\d*) from (?<from>\d*) to (?<to>\d*)")
let stacks: char[][] = Array.create numberOfStacks Array.empty
let rearrange (moveFrom: int, moveTo: int, number: int) : unit =
let leftCrates = stacks[moveFrom].Length - number
let moved =
stacks[moveFrom]
|> Seq.ofArray
|> Seq.skip leftCrates
|> (fun x -> if not isCrateMover9001 then Seq.rev x else x)
|> Array.ofSeq
stacks[moveTo] <- Array.append stacks[moveTo] moved
stacks[moveFrom] <- Array.take leftCrates stacks[moveFrom]
member _.Rearrange(command: string) : unit =
let m = commandPattern.Match(command)
let moveFrom = (m.Groups["from"].Value |> int) - 1
let moveTo = (m.Groups["to"].Value |> int) - 1
let number = m.Groups["number"].Value |> int
rearrange (moveFrom, moveTo, number)
member _.PlaceCargo(index: int, c: char) : unit =
stacks[index] <- Array.insertAt 0 c stacks[index]
member _.GetTopCrates() : string =
let topCrate (stack: char[]) : string =
match Array.tryLast stack with
| Some x -> string x
| None -> ""
stacks |> Array.fold (fun acc x -> acc + topCrate x) ""
type Input() =
member _.Compute(part: int) =
use stream = new StreamReader "./input.txt"
let mutable endOfFile = false
let mutable line = stream.ReadLine()
let numberOfStacks = (line.Length + 1) / 4
let ship = Ship(numberOfStacks, (part = 2))
while line[1] <> '1' do
let crates = line |> Seq.splitInto numberOfStacks |> Seq.indexed
for (i, x) in crates do
if x[1] <> ' ' then ship.PlaceCargo(i, x[1]) else ()
line <- stream.ReadLine()
line <- stream.ReadLine()
while (not endOfFile) do
line <- stream.ReadLine()
if (line = null) then endOfFile <- true
else if (part = 1) then ship.Rearrange(line)
else ship.Rearrange(line)
ship.GetTopCrates()
let input = Input()
let part = (Environment.GetCommandLineArgs()[1]) |> int
printfn "%s" (input.Compute(part))