Advent of Code: 2023 Day 2

R
Advent of Code 2023
Author
Published

December 13, 2023

Intro

Day 2 of AOC 2023

library(aocr)
library(tidyverse)
library(printr)

d_init <- aoc_get_data_as_tibble(2023, 2)

Part 1

Play-by-play

head(d_init)
col_1
Game 1: 20 green, 3 red, 2 blue; 9 red, 16 blue, 18 green; 6 blue, 19 red, 10 green; 12 red, 19 green, 11 blue
Game 2: 12 green, 3 blue, 16 red; 6 red, 4 blue, 12 green; 11 green, 4 red, 3 blue; 8 green, 15 red, 5 blue
Game 3: 13 blue, 4 red, 8 green; 2 green, 4 red, 19 blue; 5 blue; 10 blue, 6 green, 2 red; 19 blue; 8 blue, 6 red
Game 4: 14 green, 8 blue, 10 red; 11 green, 7 blue, 8 red; 8 green, 18 blue, 11 red
Game 5: 7 red, 7 green, 1 blue; 2 red, 1 green, 2 blue; 2 blue, 7 green; 7 red, 3 blue, 11 green
Game 6: 3 green, 1 red, 3 blue; 5 green, 19 red, 8 blue; 7 red, 2 green, 10 blue; 1 blue, 1 green, 12 red; 6 blue, 1 green, 16 red
  • Lets use the first row/game as an example. After this is figured out we can wrap it into a function to execute against each row.
game <- d_init[[1]][1]

game
[1] "Game 1: 20 green, 3 red, 2 blue; 9 red, 16 blue, 18 green; 6 blue, 19 red, 10 green; 12 red, 19 green, 11 blue"
  • Separate the game text
split_init <- str_split(unlist(game), ": ")[[1]]

split_init
[1] "Game 1"                                                                                                
[2] "20 green, 3 red, 2 blue; 9 red, 16 blue, 18 green; 6 blue, 19 red, 10 green; 12 red, 19 green, 11 blue"
  • Store the game ID
game_id <-
  split_init[1] %>%
  str_remove("Game ") %>%
  as.numeric()

game_id
[1] 1
  • Use str_split() on the second object to separate into sets
  • Clear out extra white spaces with str_squish()
  • Transform it back into a tibble
  • Add a set_id to keep track of what set the values are from for future aggregation
d_1 <-
  str_split(split_init[2], ";")[[1]] %>%
  str_squish() %>%
  as_tibble() %>%
  mutate(
    set_id = row_number()
  )

d_1
value set_id
20 green, 3 red, 2 blue 1
9 red, 16 blue, 18 green 2
6 blue, 19 red, 10 green 3
12 red, 19 green, 11 blue 4
  • Turn the value column into separate rows based on the comma delim
d_2 <- 
  d_1 %>% 
  separate_longer_delim(value, delim = ", ")

d_2
value set_id
20 green 1
3 red 1
2 blue 1
9 red 2
16 blue 2
18 green 2
6 blue 3
19 red 3
10 green 3
12 red 4
19 green 4
11 blue 4
  • Separate the number and color from the value column
  • Use convert = TRUE to auto-coerce data types
d_3 <- 
  d_2 %>% 
  separate(
    col = value,
    into = c("n", "color"),
    sep = " ",
    convert = TRUE
  ) 

d_3
n color set_id
20 green 1
3 red 1
2 blue 1
9 red 2
16 blue 2
18 green 2
6 blue 3
19 red 3
10 green 3
12 red 4
19 green 4
11 blue 4
  • Group by set and color to get the total counts
  • The summarize is likely not needed, but I added it just incase there was more than one color shown in a set
  • Get the result by checking to see if the color counts are less than or equal to the amounts given in the problem
d_4 <- 
  d_3 %>% 
  group_by(set_id, color) %>%
  summarize(
    n = sum(n),
    .groups = "drop"
  ) %>%
  mutate(
    result = case_when(
      color == "red" & n <= 12 ~ TRUE,
      color == "green" & n <= 13 ~ TRUE,
      color == "blue" & n <= 14 ~ TRUE,
      TRUE ~ FALSE
    )
  )

d_4
set_id color n result
1 blue 2 TRUE
1 green 20 FALSE
1 red 3 TRUE
2 blue 16 FALSE
2 green 18 FALSE
2 red 9 TRUE
3 blue 6 TRUE
3 green 10 TRUE
3 red 19 FALSE
4 blue 11 TRUE
4 green 19 FALSE
4 red 12 TRUE
  • If all results are TRUE, return the game_id. This is needed to summarize for the final answer
  • If not all results are not TRUE, return a 0. This will represent a game ID we want to ignore
if (all(d_4$result)) {
  result <- game_id
} else {
  result <- 0
}

result
[1] 0

Functionize it

day_2_part_1 <- function(game) {
  split_init <- str_split(unlist(game), ": ")[[1]]
  
  game_id <- split_init[1] %>%
    str_remove("Game ") %>%
    as.numeric()
  
  d <-
    str_split(split_init[2], ";")[[1]] %>%
    str_squish() %>%
    as_tibble() %>%
    mutate(
      set_id = row_number()
    ) %>%
    separate_longer_delim(value, delim = ", ") %>%
    separate(
      col = value,
      into = c("n", "color"),
      sep = " ",
      convert = TRUE
    ) %>%
    group_by(set_id, color) %>%
    summarize(
      n = sum(n),
      .groups = "drop"
    ) %>%
    mutate(
      result = case_when(
        color == "red" & n <= 12 ~ TRUE,
        color == "green" & n <= 13 ~ TRUE,
        color == "blue" & n <= 14 ~ TRUE,
        TRUE ~ FALSE
      )
    )
  
  if (all(d$result)) {
    result <- game_id
  } else {
    result <- 0
  }
  
  return(result)
}
v_res <- 
  d_init %>%
  group_split(row_id = row_number()) %>%
  map_int(day_2_part_1)

head(v_res)
[1] 0 0 0 0 5 0
sum(v_res)
[1] 2545

Part 2

As you continue your walk, the Elf poses a second question: in each game you played, what is the fewest number of cubes of each color that could have been in the bag to make the game possible?

  • For this we will need to look at each game and get the max n by color then take the product, or they call it power, of the 3 numbers
  • I will modify the summarize to take the max n by color then use the prod function to multiply them together
day_2_part_2 <- function(game) {
  split_init <- str_split(unlist(game), ": ")[[1]]
  game_id <- split_init[1] %>%
    str_remove("Game ") %>%
    as.numeric()
  d <-
    str_split(split_init[2], ";")[[1]] %>%
    str_squish() %>%
    as_tibble() %>%
    mutate(
      set_id = row_number()
    ) %>%
    separate_longer_delim(value, delim = ", ") %>%
    separate(
      col = value,
      into = c("n", "color"),
      sep = " ",
      convert = TRUE
    ) %>%
    group_by(color) %>%
    summarize(
      n = max(n),
      .groups = "drop"
    )
  
  result <- prod(d$n)
  
  return(result)
}
d_init %>%
  group_split(set_id = row_number()) %>%
  map_int(day_2_part_2) %>%
  sum()
[1] 78111

Sources

Session info

Click for session info

─ Session info ───────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.3.1 (2023-06-16 ucrt)
 os       Windows 10 x64 (build 19045)
 system   x86_64, mingw32
 ui       RTerm
 language (EN)
 collate  English_United States.utf8
 ctype    English_United States.utf8
 tz       America/Chicago
 date     2023-12-17
 pandoc   3.1.1 @ C:/Program Files/RStudio/resources/app/bin/quarto/bin/tools/ (via rmarkdown)

─ Packages ───────────────────────────────────────────────────────────────────
 ! package     * version    date (UTC) lib source
 P aocr        * 0.0.0.9000 2023-12-09 [?] Github (koderkow/aocr@24fd057)
 P backports     1.4.1      2021-12-13 [?] RSPM (R 4.3.0)
 P bit           4.0.5      2022-11-15 [?] CRAN (R 4.3.1)
 P bit64         4.0.5      2020-08-30 [?] CRAN (R 4.3.1)
 P checkmate     2.3.1      2023-12-04 [?] CRAN (R 4.3.2)
 P cli           3.6.1      2023-03-23 [?] RSPM (R 4.3.0)
 P clipr         0.8.0      2022-02-22 [?] CRAN (R 4.3.1)
 P colorspace    2.1-0      2023-01-23 [?] CRAN (R 4.3.1)
 P crayon        1.5.2      2022-09-29 [?] RSPM (R 4.3.0)
 P curl          5.0.2      2023-08-14 [?] CRAN (R 4.3.1)
 P desc          1.4.2      2022-09-08 [?] RSPM (R 4.3.0)
 P details     * 0.3.0      2022-03-27 [?] RSPM (R 4.3.0)
 P digest        0.6.33     2023-07-07 [?] RSPM (R 4.3.0)
 P dplyr       * 1.1.2      2023-04-20 [?] CRAN (R 4.3.1)
 P evaluate      0.21       2023-05-05 [?] CRAN (R 4.3.1)
 P fansi         1.0.4      2023-01-22 [?] CRAN (R 4.3.1)
 P fastmap       1.1.1      2023-02-24 [?] CRAN (R 4.3.1)
 P forcats     * 1.0.0      2023-01-29 [?] CRAN (R 4.3.1)
 P generics      0.1.3      2022-07-05 [?] CRAN (R 4.3.1)
 P ggplot2     * 3.4.3      2023-08-14 [?] CRAN (R 4.3.1)
 P glue          1.6.2      2022-02-24 [?] RSPM (R 4.3.0)
 P gtable        0.3.4      2023-08-21 [?] CRAN (R 4.3.1)
 P hms           1.1.3      2023-03-21 [?] CRAN (R 4.3.1)
 P htmltools     0.5.6      2023-08-10 [?] CRAN (R 4.3.1)
 P httr          1.4.7      2023-08-15 [?] CRAN (R 4.3.1)
 P httr2         0.2.3      2023-05-08 [?] CRAN (R 4.3.1)
 P jsonlite      1.8.7      2023-06-29 [?] CRAN (R 4.3.1)
 P knitr         1.43       2023-05-25 [?] CRAN (R 4.3.1)
 P lifecycle     1.0.3      2022-10-07 [?] RSPM (R 4.3.0)
 P lubridate   * 1.9.2      2023-02-10 [?] CRAN (R 4.3.1)
 P magrittr      2.0.3      2022-03-30 [?] RSPM (R 4.3.0)
 P munsell       0.5.0      2018-06-12 [?] CRAN (R 4.3.1)
 P pillar        1.9.0      2023-03-22 [?] CRAN (R 4.3.1)
 P pkgconfig     2.0.3      2019-09-22 [?] CRAN (R 4.3.1)
 P png           0.1-8      2022-11-29 [?] RSPM (R 4.3.0)
 P printr      * 0.3        2023-03-08 [?] CRAN (R 4.3.2)
 P purrr       * 1.0.2      2023-08-10 [?] RSPM (R 4.3.0)
 P R6            2.5.1      2021-08-19 [?] RSPM (R 4.3.0)
 P rappdirs      0.3.3      2021-01-31 [?] CRAN (R 4.3.1)
 P readr       * 2.1.4      2023-02-10 [?] CRAN (R 4.3.1)
   renv          1.0.3      2023-09-19 [1] CRAN (R 4.3.2)
 P rlang         1.1.1      2023-04-28 [?] RSPM (R 4.3.0)
 P rmarkdown     2.24       2023-08-14 [?] CRAN (R 4.3.1)
 P rprojroot     2.0.3      2022-04-02 [?] RSPM (R 4.3.0)
 P rstudioapi    0.15.0     2023-07-07 [?] CRAN (R 4.3.1)
 P scales        1.2.1      2022-08-20 [?] CRAN (R 4.3.1)
 P sessioninfo   1.2.2      2021-12-06 [?] RSPM (R 4.3.0)
 P stringi       1.7.12     2023-01-11 [?] RSPM (R 4.3.0)
 P stringr     * 1.5.0      2022-12-02 [?] RSPM (R 4.3.0)
 P tibble      * 3.2.1      2023-03-20 [?] CRAN (R 4.3.1)
 P tidyr       * 1.3.0      2023-01-24 [?] CRAN (R 4.3.1)
 P tidyselect    1.2.0      2022-10-10 [?] CRAN (R 4.3.1)
 P tidyverse   * 2.0.0      2023-02-22 [?] CRAN (R 4.3.1)
 P timechange    0.2.0      2023-01-11 [?] CRAN (R 4.3.1)
 P tzdb          0.4.0      2023-05-12 [?] CRAN (R 4.3.1)
 P utf8          1.2.3      2023-01-31 [?] CRAN (R 4.3.1)
 P vctrs         0.6.3      2023-06-14 [?] CRAN (R 4.3.1)
 P vroom         1.6.3      2023-04-28 [?] CRAN (R 4.3.1)
 P withr         2.5.0      2022-03-03 [?] CRAN (R 4.3.1)
 P xfun          0.40       2023-08-09 [?] RSPM (R 4.3.0)
 P xml2          1.3.5      2023-07-06 [?] RSPM (R 4.3.0)
 P yaml          2.3.7      2023-01-23 [?] RSPM (R 4.3.0)

 [1] C:/Users/kypap/Documents/projects/quarto-site/renv/library/R-4.3/x86_64-w64-mingw32
 [2] C:/Users/kypap/AppData/Local/R/cache/R/renv/sandbox/R-4.3/x86_64-w64-mingw32/bd3f13aa

 P ── Loaded and on-disk path mismatch.

──────────────────────────────────────────────────────────────────────────────