package main import ( "flag" "fmt" "math" "os" "regexp" "strconv" "strings" ) var ( inputFile = flag.String("input", "input.txt", "input filename") subsetRegex = regexp.MustCompile(`(?mi)(\d+)+\s(\w+)([,;]?)`) startRegex = regexp.MustCompile(`(?mi)Game\s(\d+):`) ) const ( BlueCube = "blue" GreenCube = "green" RedCube = "red" MaxRed = 12 MaxGreen = 13 MaxBlue = 14 ) func main() { flag.Parse() input, err := os.ReadFile(*inputFile) if err != nil { panic(err) } var sum, powSum int for _, line := range strings.Split(string(input), "\n") { if strings.TrimSpace(line) == "" { continue } // find id idMatch := startRegex.FindAllStringSubmatch(line, -1) id, err := strconv.Atoi(idMatch[0][1]) if err != nil { panic(err) } // find sets of digit + color + separator (e.g. "3 blue,") subsets := subsetRegex.FindAllStringSubmatch(line, -1) var red, green, blue int var minRed, minGreen, minBlue int possible := true for _, subset := range subsets { cubeAmount, err := strconv.Atoi(subset[1]) if err != nil { panic(err) } // add cube amount to set switch strings.ToLower(subset[2]) { case BlueCube: blue += cubeAmount case GreenCube: green += cubeAmount case RedCube: red += cubeAmount } // end of set reached if subset[3] == "" || subset[3] == ";" { if red > MaxRed || green > MaxGreen || blue > MaxBlue { possible = false } minBlue = int(math.Max(float64(minBlue), float64(blue))) minRed = int(math.Max(float64(minRed), float64(red))) minGreen = int(math.Max(float64(minGreen), float64(green))) red = 0 blue = 0 green = 0 } } // end of game reached powSum += minRed * minGreen * minBlue if possible { fmt.Printf("%d possible\n", id) sum += id } } fmt.Printf("Sum of IDs: %d\n", sum) fmt.Printf("Sum of the power of sets: %d", powSum) }