# AoC 2023, Day 2, Cube Conundrum

Today’s puzzle is Cube Conundrum.

## Part 1

I will start by defining a few types, cube, game.

```
type Set = Set of red: int * green: int * blue: int
type Game = Game of no: int * sets: Set list
```

I need a way to see if a given game is valid (a game is valid if all sets in the game are valid).

```
let validSet (Set (bagRed, bagGreen, bagBlue)) (Set (setRed, setGreen, setBlue)) =
setRed <= bagRed && setGreen <= bagGreen && setBlue <= bagBlue
let validGame bag (Game (no, sets)) =
if Seq.forall (validSet bag) sets then Some no else None
```

I need to be able to read the input text

```
let readText (fullText: string) =
let readCubes (Set (red,green,blue)) (cubeText: string) =
match cubeText.Split(' ') with
| [| x; "red" |] -> (Set (int x, green, blue))
| [| x; "green" |] -> (Set (red, int x, blue))
| [| x; "blue" |] -> (Set (red, green, int x))
| _ -> (Set (red, green, blue))
let readSet (setText: string) =
setText.Split(',')
|> Seq.map (fun x -> x.Trim())
|> Seq.fold readCubes (Set (0,0,0))
let readGameId (game: string) = game.Split(' ')[1] |> int
let readGame (gameText: string) =
match gameText.Split(':') with
| [| game; sets |] -> Some (Game (readGameId game, sets.Split(';') |> Seq.map readSet |> Seq.toList))
| _ -> None
fullText.Split("\n") |> Seq.choose readGame
```

I will now create a bag (which is just a set).

`let bag = Set (12, 13, 14)`

And then read the example text, convert it to a list of games, validate each one, and then get a sum of the numbers.

```
let sampleText =
"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"
sampleText
|> readText
|> Seq.choose (validGame bag)
|> Seq.sum
```

```
8
```

The result is correct for the example, and my answer for the puzzle is correct as well.

## Part 2

In Part 2 I need to find the minimum bag needed for each game. This can be done by fining the maximum of each cube colour in each game.

```
let minSet (Game (_, sets)) =
let getRed (Set(r,_,_)) = r
let getGreen (Set(_,g,_)) = g
let getBlue (Set(_,_,b)) = b
let maxBy g = sets |> Seq.map g |> Seq.max
Set (maxBy getRed, maxBy getGreen, maxBy getBlue)
```

I need a small function to calculate the power of each games minimum bag.

`let powerCube (Set (red, green, blue)) = red * green * blue`

Now I put this all together and see if my results are close.

```
sampleText
|> readText
|> Seq.map minSet
|> Seq.map powerCube
|> Seq.sum
```

```
2286
```

`2286` is the result I am expecting with the example input. My final answer is also correct, I have one more gold star.