-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday02.fsx
100 lines (79 loc) · 2.68 KB
/
day02.fsx
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
open System;
open System.Text.RegularExpressions
// --- PART A ---
let grabExpression = Regex "([0-9]+) ([a-z]+)"
let gameExpression = Regex "Game ([0-9]+): (.+)"
type Grab = {
Colour: string
Total: int
}
let splitRound (input: string) =
input.Split ';'
let parseGrabValues (input: string) =
grabExpression.Matches input
|> Seq.map (fun m ->
let total = m.Groups[1].Value |> int
let colour = m.Groups[2].Value
{ Total = total; Colour = colour }
)
let parseRounds (input: string) =
splitRound input
|> Seq.map parseGrabValues
let parseGame (input: string) =
let game = gameExpression.Match input
let gameNum = game.Groups[1].Value |> int
let rounds = game.Groups[2].Value |> parseRounds
{| Num = gameNum; Rounds = rounds |}
let colours = [
"red", 12;
"green", 13;
"blue", 14]
/// determines if the set of grabs matches the colour maximums
let roundConforms (maximums: Map<string,int>) (grabs: seq<Grab>) =
grabs
|> Seq.forall (fun g ->
let col = maximums[g.Colour]
g.Total <= col
)
let partA (input: seq<string>) =
let maximums = colours |> Map.ofList
let rules = (roundConforms maximums)
input
|> Seq.map parseGame // extract game
|> Seq.filter (fun g ->
g.Rounds |> Seq.forall rules
) // ensure game does not exceed the cube limits
|> Seq.map (fun g -> g.Num) // extract game number
|> Seq.sum
let partAExample = [
"Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green";
"Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue";
"Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red";
"Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red";
"Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"
]
8 = partA partAExample
let lines = (IO.File.ReadAllLines "day02inp.txt")
partA lines
// --- PART B ----
let setMaxTotal (total: Map<string, int>) (g: Grab) =
total.Change(g.Colour, (fun v ->
match v with
| Some t -> Some(max t g.Total)
| None -> Some(g.Total)))
// retrieves the minimum of each colour
let maximumColours (total: Map<string, int>) (grabs: seq<Grab>) =
(total, grabs) ||> Seq.fold setMaxTotal
let maximumRounds (grabs: seq<seq<Grab>>) =
(Map.empty, grabs) ||> Seq.fold maximumColours
let powerColours (total: Map<string, int>) =
total |> Map.toSeq |> Seq.map (fun (k, v) -> v) |> Seq.reduce (fun a b -> a * b)
let partB (input: seq<string>) =
input
|> Seq.map parseGame // extract game
|> Seq.map (fun g ->
maximumRounds g.Rounds
|> powerColours)
|> Seq.sum
2286 = partB partAExample
partB lines