Day 02

Author

Hendrik Wagenseil

Data

Load and preview the data set.

y = "2023"
d = "02"

ifl = file.path(
  here::here()
  , y
  , "data"
  , paste0(y, "-day", d, "input")
)

txt = readLines(ifl)
head(txt)
[1] "Game 1: 1 green, 2 blue; 15 blue, 12 red, 2 green; 4 red, 6 blue; 10 blue, 8 red; 3 red, 12 blue; 1 green, 12 red, 8 blue"     
[2] "Game 2: 5 green, 2 red, 18 blue; 18 blue, 6 red, 9 green; 6 blue, 3 green; 6 green, 1 red, 9 blue; 19 blue, 2 green, 6 red"    
[3] "Game 3: 16 red, 10 green; 12 red, 6 blue, 9 green; 10 green, 5 blue; 10 green, 16 red; 5 red, 8 green, 8 blue"                 
[4] "Game 4: 9 blue, 20 green; 1 red, 3 blue, 10 green; 7 blue, 18 green; 4 blue, 20 green; 8 blue, 1 green, 1 red; 1 green"        
[5] "Game 5: 3 green, 8 red; 1 blue, 10 red; 6 red, 4 green; 8 red, 1 blue, 3 green; 1 blue, 4 green, 3 red; 1 green, 1 blue, 4 red"
[6] "Game 6: 7 green, 15 red, 11 blue; 2 red, 12 blue; 11 red, 11 green"                                                            

Part I

Colored cubes (red, green, blue) are drawn from a bag with replacement. Several iterations compose a game. The task is to identify all games being possible if the bag contained

  • 12 red cubes
  • 13 green cubes
  • 14 blue cubes

The solution is the sum of the ids of these games.

Overall, the iterations per game do not matter here. The problem simplifies to identify games where the number of cubes drawn in a particular color exceeds the given amount of cubes in this color.

Approach:

  • replace the prefix “Game X:” from every vector element as the game id is equal to the index
  • split the game into single cubes
  • get the maximum number of cubes per colors and per game
  • identify games where the maximum number of cubes in at least one color exceeds the given amount of cubes
splitgame = function(
    x
){

  x = gsub("^.*?:", replacement = "", x = x)
  unlist(
    strsplit(x, split = ";|,")
  )
  
}

maxcubes = function(
    x
    , colors = c("red", "green", "blue")
){
  
  vapply(
    colors
    , FUN = \(c){
      v = grep(c, x = x, value = TRUE)
      v = gsub(c, replacement = "", x = v)
      v = trimws(v)
      max(0L, as.integer(v))
    }
    , FUN.VALUE = integer(1L)
  )
  
}  

games = Map(
  splitgame
  , x = txt
) |> 
  unname()

cubes = Map(
  maxcubes
  , x = games
)

possible = lapply(
  cubes
  , FUN = \(i){
    all(i <= c(12, 13, 14))
  }
) |> 
  unlist() 

sum(which(possible))
[1] 2913

Approach:

  • split each game into single cubes, drop prefix “Game X:”
  • get the maximum number of cubes per colors and per game
  • identify games where the maximum number of cubes in at least one color exceeds the given amount of cubes
import re
import numpy as np

def maxcubes(x: str):
  x = re.split(',|;|:', x)[1:]
  cbs = []
  for col in ['red', 'green', 'blue']:
    c = [int(g.replace(col, '')) for g in x if col in g]
    cbs.append(max(c))
  return cbs  

cubes = map(maxcubes, r.txt)
cubes = list(cubes)
cubes = np.array(cubes)

idx = 0
for i, x in enumerate(cubes):
  if all(cubes[i] <= np.array([12, 13, 14])):
    idx += i + 1
  
idx
2913

Part II

Per game, determine the minimum number of cubes per color required to play that game. Calculate the power of the game, i.e. multiply the numbers of the minimum set.

Approach:

  • interim step of part I was a list containing the maximum number of cubes per color in a given game
  • per game, multiply the elements per game and calculate the sum
pow = Map(
  prod
  , ... = cubes
) |>
  unlist() 

sum(pow)
[1] 55593

Approach:

  • interim step of part I was a numpy array containing the maximum number of cubes per color in a given game
  • calculate the product of the array along dimension 1 (rows) and calculate the sum
pow = np.prod(cubes, axis = 1)
sum(pow)
55593