-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday18_part02.fs
79 lines (65 loc) · 2.27 KB
/
day18_part02.fs
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
module day18_part02
open AdventOfCode_2018.Modules
type Acre =
| Open
| Trees
| Lumberyard
let charToAcre =
function
| '.' -> Open
| '|' -> Trees
| '#' -> Lumberyard
| c -> failwithf "Invalid Char %c" c
let parseAcres = array2D >> Array2D.map charToAcre
let neighbours x y =
[|
(x - 1, y - 1); (x, y - 1); (x + 1, y - 1);
(x - 1, y); (x + 1, y); (x - 1, y + 1);
(x, y + 1);(x + 1, y + 1)
|]
type NeighbourCounts = {
openAcres: int;
treeAcres: int;
lumberyards: int
}
let zeroCounts = { openAcres=0; treeAcres=0; lumberyards=0 }
let addNeighbourToCounts counts =
function
| Open -> {counts with openAcres=counts.openAcres + 1}
| Trees -> {counts with treeAcres=counts.treeAcres + 1}
| Lumberyard -> {counts with lumberyards=counts.lumberyards + 1}
let getNextCellState cur {treeAcres=trees; lumberyards=lumberyards} =
match cur with
| Open -> if trees >= 3 then Trees else Open
| Trees -> if lumberyards >= 3 then Lumberyard else Trees
| Lumberyard -> if lumberyards = 0 || trees = 0 then Open else Lumberyard
let step grid =
let width = Array2D.length1 grid
let height = Array2D.length2 grid
let inBounds (x, y) = 0 <= x && x < width && 0 <= y && y < height
let getNextState x y cur =
neighbours x y
|> Array.filter inBounds
|> Array.map (fun (x, y) -> grid.[x, y])
|> Array.fold addNeighbourToCounts zeroCounts
|> getNextCellState cur
Array2D.mapi getNextState grid
let score grid =
let counts = grid |> Seq.cast<Acre> |> Seq.fold addNeighbourToCounts zeroCounts
counts.lumberyards * counts.treeAcres
let stepN n grid =
Seq.init n id |> Seq.fold (fun g _ -> step g) grid
let totalAfter grid steps=
let rec stepCached i grid cache =
match Map.tryFind grid cache with
| Some x ->
let cycleLength = i - x
let stepsToTarget = (steps - x) % cycleLength
grid |> stepN stepsToTarget |> score
| None -> stepCached (i + 1) (step grid) (Map.add grid i cache)
stepCached 0 grid Map.empty
let execute =
let path = "day18/day18_input.txt"
let content = LocalHelper.GetLinesFromFile path
let tiles = parseAcres content
totalAfter tiles 1000000000