-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday22_part01.fs
108 lines (93 loc) · 3.13 KB
/
day22_part01.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
module day22_part01
open AdventOfCode_2018.Modules
open System
open System.Text.RegularExpressions
let toLines (text:string) =
text.Split([|'\r'; '\n'|], StringSplitOptions.RemoveEmptyEntries)
let groupValue (m:Match) (i:int) = m.Groups.[i].Value
let rxMatch pattern str = Regex.Match(str, pattern)
let toString (chrs : seq<char>) = String(Array.ofSeq chrs)
(* ================ Part A ================ *)
type Location = int*int
type Type = Rocky | Narrow | Wet
type Times = {Torch: int; Gear: int; Neither: int}
type Region = {
Location: Location;
Type: Type;
Erosion: int;
Times: Times}
type Cave = { Map: Region[,]; MaxX: int; MaxY:int}
let noRoute = Int32.MaxValue - 8
let defaultTimes = {Torch = noRoute; Gear = noRoute; Neither = noRoute}
let mouthTimes = {defaultTimes with Torch = 0; Gear = 7}
let nonRegion = {
Location= (-1, -1);
Type= Rocky;
Erosion= -1;
Times= defaultTimes}
let parse text =
let lines = text |> toLines
let depth = rxMatch "\d+" lines.[0] |> (fun m -> m.Value |> int)
let (x,y) = rxMatch "(\d+),(\d+)" lines.[1] |> (fun mtch ->
let grp idx = groupValue mtch idx
let grpi = grp >> int
grpi 1, grpi 2)
(depth, (x, y))
let display tLoc (cave:Cave) =
let symbol {Type=typ} =
match typ with
| Rocky -> '.'
| Wet -> '='
| Narrow -> '|'
Array.init (cave.MaxY+1) (fun y ->
Array.init (cave.MaxX+1) (fun x ->
cave.Map.[x,y] |> function
| {Location = (0,0)} -> 'M'
| {Location = loc} when loc = tLoc-> 'T'
| r -> symbol r))
|> Array.iter (fun (line:char[]) -> printfn "%s" (toString line))
cave
let getType erosion =
match erosion % 3 with
| 0 -> Rocky
| 1 -> Wet
| 2 -> Narrow
let newRegion depth tLoc (cave:Cave) loc =
let erosion =
let (x,y) = loc
let geoIndex =
if loc = (0,0) || loc = tLoc then 0 else
if y = 0 then x * 16807 else
if x = 0 then y * 48271 else
cave.Map.[x-1,y].Erosion * cave.Map.[x,y-1].Erosion
(geoIndex + depth) % 20183
{Location = loc;
Type = (getType erosion);
Erosion = erosion;
Times = defaultTimes}
let enumCoords (grid: 'a[,]) =
let (X,Y) = grid.GetUpperBound(0), grid.GetUpperBound(1)
seq{for y in 0..Y do for x in 0..X do yield (x,y)}
let buildCave depth maxes tLoc : Cave =
let (X,Y) = maxes
let map = Array2D.create (X+1) (Y+1) nonRegion
let cave = {Map = map; MaxX = X; MaxY = Y}
enumCoords map
|> Seq.iter (fun (x,y) ->
map.[x,y] <- (newRegion depth tLoc cave (x,y)))
map.[0,0] <- {map.[0,0] with Times = mouthTimes}
cave
let assessRisk cave =
cave.Map
|> Seq.cast<Region>
|> Seq.sumBy (fun {Type=typ} ->
match typ with Rocky -> 0 | Wet -> 1 | Narrow -> 2)
let Part1 (input : string) =
let depth, targetLoc = parse input
buildCave depth targetLoc targetLoc
//|> display targetLoc
|> assessRisk
let execute =
let path = "day22/day22_input.txt"
let content = LocalHelper.GetContentFromFile path
Part1 content