2023-12-02 17:00:27 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"log"
|
2023-12-05 19:38:55 +00:00
|
|
|
|
|
|
|
"codeflow.dananglin.me.uk/apollo/advent-of-code/internal/common"
|
2023-12-02 17:00:27 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
filename := "2023/day-2/files/input"
|
|
|
|
|
2023-12-05 19:38:55 +00:00
|
|
|
games, err := common.ReadFile(filename)
|
2023-12-02 17:00:27 +00:00
|
|
|
if err != nil {
|
2023-12-02 17:46:44 +00:00
|
|
|
log.Fatalf("ERROR: unable to read from %s, %v\n", filename, err)
|
2023-12-02 17:00:27 +00:00
|
|
|
}
|
|
|
|
|
2023-12-02 17:46:44 +00:00
|
|
|
sumOfIDs, err := sumOfGameIDs(games)
|
2023-12-02 17:00:27 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("ERROR: unable to calculate the sum of the IDs of the valid games; %v\n", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Printf("Total sum of the IDs of the valid games: %d\n", sumOfIDs)
|
|
|
|
|
2023-12-02 17:46:44 +00:00
|
|
|
sumOfPower, err := sumOfThePowerOfTheCubes(games)
|
2023-12-02 17:00:27 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("ERROR: unable to calculate the sum of the power of cubes; %v\n", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Printf("Total sum of the power of cubes: %d\n", sumOfPower)
|
|
|
|
}
|
|
|
|
|
|
|
|
// sumOfGameIDs solves Part 1
|
2023-12-02 17:46:44 +00:00
|
|
|
func sumOfGameIDs(content []string) (int, error) {
|
2023-12-02 17:00:27 +00:00
|
|
|
sum := 0
|
|
|
|
|
2023-12-02 17:46:44 +00:00
|
|
|
for i := range content {
|
|
|
|
if len(content[i]) == 0 {
|
2023-12-02 17:00:27 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-12-02 17:46:44 +00:00
|
|
|
game, err := parseGame(content[i])
|
2023-12-02 17:00:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, fmt.Errorf("unable to parse %q; %w", game, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if validGame(game.Sets) {
|
|
|
|
sum = sum + game.ID
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return sum, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// sumOfThePowerOfTheCubes solves Part 2
|
2023-12-02 17:46:44 +00:00
|
|
|
func sumOfThePowerOfTheCubes(content []string) (int, error) {
|
2023-12-02 17:00:27 +00:00
|
|
|
sum := 0
|
|
|
|
|
2023-12-02 17:46:44 +00:00
|
|
|
for i := range content {
|
|
|
|
if len(content[i]) == 0 {
|
2023-12-02 17:00:27 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-12-02 17:46:44 +00:00
|
|
|
game, err := parseGame(content[i])
|
2023-12-02 17:00:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, fmt.Errorf("unable to parse %q; %w", game, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
fewestCubeSet := fewestSet(game.Sets)
|
|
|
|
|
|
|
|
sum = sum + (fewestCubeSet.Red * fewestCubeSet.Green * fewestCubeSet.Blue)
|
|
|
|
}
|
|
|
|
|
|
|
|
return sum, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func validGame(sets []Set) bool {
|
|
|
|
const (
|
|
|
|
maxRed = 12
|
|
|
|
maxGreen = 13
|
|
|
|
maxBlue = 14
|
|
|
|
)
|
|
|
|
|
|
|
|
for _, set := range sets {
|
|
|
|
switch {
|
|
|
|
case set.Red > maxRed:
|
|
|
|
return false
|
|
|
|
case set.Blue > maxBlue:
|
|
|
|
return false
|
|
|
|
case set.Green > maxGreen:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func fewestSet(sets []Set) Set {
|
|
|
|
result := Set{0, 0, 0}
|
|
|
|
|
|
|
|
for _, set := range sets {
|
|
|
|
if set.Red > result.Red {
|
|
|
|
result.Red = set.Red
|
|
|
|
}
|
|
|
|
|
|
|
|
if set.Green > result.Green {
|
|
|
|
result.Green = set.Green
|
|
|
|
}
|
|
|
|
|
|
|
|
if set.Blue > result.Blue {
|
|
|
|
result.Blue = set.Blue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|