blob: 7bad2693c5e72b78d7fb01a8d23b1986b51b3775 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
module Day05
open System
open System.IO
open FParsec
open Common
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)
Util.parse pMove str |> Move
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
str
|> Util.parse pHeader
|> 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
|