Advent of Code 2021

Kyle Harris

2021-12-21

Packages

library(tidyverse)
library(zoo)
library(details)

Globally set show_col_types = FALSE.

read_tsv <- partial(read_tsv, show_col_types = FALSE)

Day 1

Setup

d <- "data/01.txt" |>
  read_lines() |>
  as.numeric() |>
  enframe(value = "x")

d
## # A tibble: 2,000 x 2
##     name     x
##     
##  1     1   174
##  2     2   180
##  3     3   179
##  4     4   186
##  5     5   184
##  6     6   176
##  7     7   177
##  8     8   190
##  9     9   173
## 10    10   174
## # ... with 1,990 more rows

Part 1

d_1 <-
  d |>
  mutate(
    diff = x - lag(x)
  ) |>
  summarize(
    x = sum(diff > 0, na.rm = TRUE)
  )

d_1
## # A tibble: 1 x 1
##       x
##   
## 1  1316

Part 2

d_2 <- d

d_2$y <- rollsum(d$x, 3, align = "left", fill = 0)

d_2
## # A tibble: 2,000 x 3
##     name     x     y
##      
##  1     1   174   533
##  2     2   180   545
##  3     3   179   549
##  4     4   186   546
##  5     5   184   537
##  6     6   176   543
##  7     7   177   540
##  8     8   190   537
##  9     9   173   523
## 10    10   174   525
## # ... with 1,990 more rows
d_2 |>
  mutate(
    diff = y - lag(y)
  ) |>
  summarize(
    y = sum(diff > 0, na.rm = TRUE)
  )
## # A tibble: 1 x 1
##       y
##   
## 1  1344

Day 2

Setup

d_init <- read_tsv(
  file = "data/02.txt",
  col_names = FALSE
)

d <-
  d_init |>
  separate(
    col = X1,
    into = c("position", "unit"),
    convert = TRUE
  ) |>
  mutate(
    unit = if_else(
      condition = position == "up",
      true = unit * -1L,
      false = unit
    ),
    group = if_else(
      condition = position == "forward",
      true = "x",
      false = "y"
    )
  )

d
## # A tibble: 1,000 x 3
##    position  unit group
##         
##  1 forward      4 x    
##  2 forward      6 x    
##  3 down         8 y    
##  4 forward      3 x    
##  5 forward      9 x    
##  6 down         7 y    
##  7 down         7 y    
##  8 down         1 y    
##  9 forward      1 x    
## 10 forward      5 x    
## # ... with 990 more rows

Part 1

d |>
  group_by(group) |>
  summarize(
    units = sum(unit)
  ) |>
  pull(units) |>
  prod()
## [1] 1714680

Part 2

d |>
  mutate(
    aim = cumsum(ifelse(group == "y", unit, 0))
  ) |>
  filter(group == "x") |>
  summarize(
    x = sum(unit),
    y = sum(unit * aim),
    solution = x * y
  )
## # A tibble: 1 x 3
##       x      y   solution
##           
## 1  1980 991459 1963088820

Day 3

Setup

d_init <-
  read_tsv(
    file = "data/03.txt",
    col_names = FALSE
  )

n_cols <- nchar(d_init$X1[1])

col_names <- paste0(
  "col_",
  str_pad(0:n_cols, width = 2, pad = 0)
)

col_names
##  [1] "col_00" "col_01" "col_02" "col_03" "col_04" "col_05" "col_06" "col_07"
##  [9] "col_08" "col_09" "col_10" "col_11" "col_12"
d <-
  d_init |>
  separate(
    col = X1,
    into = col_names,
    sep = "",
    convert = TRUE
  ) |>
  select(-1)

d
## # A tibble: 1,000 x 12
##    col_01 col_02 col_03 col_04 col_05 col_06 col_07 col_08 col_09 col_10 col_11
##                         
##  1      1      1      1      1      1      0      1      1      0      1      1
##  2      1      0      0      1      1      1      0      0      0      1      1
##  3      0      1      1      1      0      1      1      1      1      1      0
##  4      0      1      1      0      1      1      0      1      0      0      1
##  5      0      0      1      0      1      0      0      0      1      0      1
##  6      1      1      1      1      0      1      0      0      1      0      0
##  7      0      1      0      0      0      1      1      1      0      0      1
##  8      1      0      0      0      0      1      0      0      1      1      1
##  9      1      1      0      1      0      1      0      1      0      0      0
## 10      1      0      0      0      0      1      1      0      0      0      1
## # ... with 990 more rows, and 1 more variable: col_12 

Part 1

d_1 <-
  d |>
  pivot_longer(
    cols = everything()
  ) |>
  count(name, value) |>
  group_by(name) |>
  summarize(
    gamma = value[which.max(n)],
    epsilon = value[which.min(n)]
  )

d_1
## # A tibble: 12 x 3
##    name   gamma epsilon
##         
##  1 col_01     1       0
##  2 col_02     0       1
##  3 col_03     0       1
##  4 col_04     1       0
##  5 col_05     1       0
##  6 col_06     1       0
##  7 col_07     0       1
##  8 col_08     1       0
##  9 col_09     1       0
## 10 col_10     0       1
## 11 col_11     0       1
## 12 col_12     0       1
gamma <-
  paste0(d_1$gamma, collapse = "") |>
  strtoi(base = 2)

epsilon <-
  paste0(d_1$epsilon, collapse = "") |>
  strtoi(base = 2)

gamma * epsilon
## [1] 3969000

Part 2

Reproduce Example

Recreating the work and results in the example help build the solution.

example_d_init <- c(
  "00100", "11110", "10110",
  "10111", "10101", "01111",
  "00111", "11100", "10000",
  "11001", "00010", "01010"
) |>
  enframe(value = "X1")

example_n_cols <- nchar(example_d_init$X1[1])

example_col_names <- paste0(
  "col_",
  str_pad(0:example_n_cols, width = 2, pad = 0)
)

example_d <-
  example_d_init |>
  separate(
    col = X1,
    into = example_col_names,
    sep = "",
    convert = TRUE
  ) |>
  select(-(1:2))

example_d
## # A tibble: 12 x 5
##    col_01 col_02 col_03 col_04 col_05
##             
##  1      0      0      1      0      0
##  2      1      1      1      1      0
##  3      1      0      1      1      0
##  4      1      0      1      1      1
##  5      1      0      1      0      1
##  6      0      1      1      1      1
##  7      0      0      1      1      1
##  8      1      1      1      0      0
##  9      1      0      0      0      0
## 10      1      1      0      0      1
## 11      0      0      0      1      0
## 12      0      1      0      1      0
i <- 1
i_max <- ncol(example_d)
d_oxygen <- d_co2 <- example_d

while (i <= i_max) {
  ref_col <- rlang::sym(example_col_names[i + 1])
  
  d_oxygen_count <-
    d_oxygen |>
    add_count({{ ref_col }}, name = "n")
  
  d_co2_count <-
    d_co2 |>
    add_count({{ ref_col }}, name = "n")
  
  if (length(unique(d_oxygen_count$n)) == 1) {
    d_oxygen <-
      d_oxygen_count |>
      filter({{ ref_col }} == 1)
    
    d_co2 <-
      d_co2_count |>
      filter({{ ref_col }} == 0)
    
  } else {
    d_oxygen <-
      d_oxygen_count |>
      filter(n == max(n))
    
    d_co2 <-
      d_co2_count |>
      filter(n == min(n))
  }
  
  i <- i + 1
}
oxygen <-
  d_oxygen |>
  select(-n) |>
  unite(
    col = binary,
    everything(),
    sep = ""
  ) |>
  mutate(decimal = strtoi(binary, base = 2))

oxygen
## # A tibble: 1 x 2
##   binary decimal
##       
## 1 10111       23
co2 <-
  d_co2 |>
  select(-n) |>
  unite(
    col = binary,
    everything(),
    sep = ""
  ) |>
  mutate(decimal = strtoi(binary, base = 2))

co2
## # A tibble: 1 x 2
##   binary decimal
##       
## 1 01010       10
## Matches!
oxygen$decimal * co2$decimal
## [1] 230

Translate example code for solution

i <- 1
i_max <- ncol(d)
d_oxygen <- d_co2 <- d

while (i <= i_max) {
  ref_col <- rlang::sym(col_names[i + 1])
  
  d_oxygen_count <-
    d_oxygen |>
    add_count({{ ref_col }}, name = "n")
  
  d_co2_count <-
    d_co2 |>
    add_count({{ ref_col }}, name = "n")
  
  if (nrow(d_oxygen_count) == 1) {
    ## If there is only one row, do nothing
    d_oxygen <- d_oxygen_count
    
  } else if (length(unique(d_oxygen_count$n)) == 1) {
    ## If all counts are the same, keep the 1's
    d_oxygen <-
      d_oxygen_count |>
      filter({{ ref_col }} == 1)
    
    ## If there are no 1's, do not remove anything
    if (nrow(d_oxygen) == 0) {
      d_oxygen <- d_oxygen_count
    }
    
  } else {
    ## Keep the most common value
    d_oxygen <-
      d_oxygen_count |>
      filter(n == max(n))
  }
  
  if (nrow(d_co2_count) == 1) {
    ## If there is only one row, do nothing
    d_co2 <- d_co2_count
    
  } else if (length(unique(d_co2_count$n)) == 1) {
    ## If all counts are the same, keep the 0's
    d_co2 <-
      d_co2_count |>
      filter({{ ref_col }} == 0)
    
    ## If there are no 0's, do not remove anything
    if (nrow(d_co2) == 0) {
      d_co2 <- d_co2_count
    }
    
  } else {
    ## Keep the least common value
    d_co2 <-
      d_co2_count |>
      filter(n == min(n))
  }
  
  i <- i + 1
}
oxygen <-
  d_oxygen |>
  select(-n) |>
  unite(
    col = binary,
    everything(),
    sep = ""
  ) |>
  mutate(decimal = strtoi(binary, base = 2))

oxygen
## # A tibble: 1 x 2
##   binary       decimal
##             
## 1 100111001101    2509
co2 <-
  d_co2 |>
  select(-n) |>
  unite(
    col = binary,
    everything(),
    sep = ""
  ) |>
  mutate(decimal = strtoi(binary, base = 2))

co2
## # A tibble: 1 x 2
##   binary       decimal
##             
## 1 011010100101    1701
oxygen$decimal * co2$decimal
## [1] 4267809

Day 4

Setup

bingo_numbers <- read_lines(
  file = "data/04.txt",
  n_max = 1
) %>% 
  str_split(",") %>% 
  unlist() %>% 
  as.integer()

bingo_numbers
##   [1]  4 75 74 31 76 79 27 19 69 46 98 59 83 23 90 52 87  6 11 92 80 51 43  5 94
##  [26] 17 15 67 25 30 48 47 62 71 85 58 60  1 72 99  3 35 42 10 96 49 37 36  8 44
##  [51] 70 40 45 39  0 63  2 78 68 53 50 77 20 55 38 86 54 93 26 88 12 91 95 34  9
##  [76] 14 33 66 41 13 28 57 29 73 56 22 89 21 64 61 32 65 97 84 18 82 81  7 16 24
d_init <- read_tsv(
  file = "data/04.txt",
  skip = 1,
  col_names = FALSE
)

d_init
## # A tibble: 500 x 1
##    X1            
##             
##  1 30 46 94 20  2
##  2 53 67 69 75 65
##  3 27 24 85 28 60
##  4 57 58 42 36 78
##  5 35 98 87 91 93
##  6 72 71 91 73 19
##  7 2 13 14  8 74 
##  8 42 34 31 56  9
##  9 82 59 44 67 79
## 10 49  6 98 10 30
## # ... with 490 more rows
(d_rows <- nrow(d_init))
## [1] 500
(col_names <- str_c("col_", 1:5))
## [1] "col_1" "col_2" "col_3" "col_4" "col_5"
l_d <-
  d_init %>% 
  separate(
    col = X1,
    into = col_names,
    convert = TRUE
  ) %>% 
  mutate(
    id = sort(rep(1:100, 5))
  ) %>% 
  group_split(id, .keep = FALSE)

l_d[1:3]
## 
## >[3]>
## [[1]]
## # A tibble: 5 x 5
##   col_1 col_2 col_3 col_4 col_5
##       
## 1    30    46    94    20     2
## 2    53    67    69    75    65
## 3    27    24    85    28    60
## 4    57    58    42    36    78
## 5    35    98    87    91    93
## 
## [[2]]
## # A tibble: 5 x 5
##   col_1 col_2 col_3 col_4 col_5
##       
## 1    72    71    91    73    19
## 2     2    13    14     8    74
## 3    42    34    31    56     9
## 4    82    59    44    67    79
## 5    49     6    98    10    30
## 
## [[3]]
## # A tibble: 5 x 5
##   col_1 col_2 col_3 col_4 col_5
##       
## 1    95    24    25    11    34
## 2    57    65    41    92     8
## 3    91    26     1    62    38
## 4    47    93     4    37     0
## 5    15    44    33    20    97

Part 1

l_d_1 <- l_d
bingo_check <- TRUE
i <- 1
winning_board <- numeric()

while (bingo_check) {
  print(i)
  bingo_call <- bingo_numbers[i]
  
  for (j in seq_along(l_d_1)) {
    ## Update values to 0 that are called
    l_d_1[[j]] <-
      l_d_1[[j]] %>% 
      mutate(
        across(
          .fns = ~ ifelse(
            test = .x == bingo_call,
            yes = 0,
            no = .x
          )
        )
      )
    
    if (any(colSums(l_d_1[[j]]) == 0 | rowSums(l_d_1[[j]]) == 0)) {
      print("Bingo!")
      print(str_c("Winning number was ", bingo_call))
      winning_board <- j
      bingo_check <- FALSE
      break
    }
  }
  
  i <- i + 1
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
## [1] 11
## [1] 12
## [1] 13
## [1] 14
## [1] 15
## [1] 16
## [1] 17
## [1] 18
## [1] 19
## [1] 20
## [1] 21
## [1] 22
## [1] "Bingo!"
## [1] "Winning number was 51"
winning_board
## [1] 34
l_d_1[[winning_board]]
## # A tibble: 5 x 5
##   col_1 col_2 col_3 col_4 col_5
##       
## 1     0    18     0    35    55
## 2     0    85     0    56    82
## 3     0    26    24    29    43
## 4     0     0     0    45    13
## 5     0    12    99    94    47
(bingo_sum <- sum(l_d_1[[winning_board]]))
## [1] 763
bingo_call * bingo_sum
## [1] 38913

Part 2

l_d_2 <- l_d
bingo_check <- TRUE
i <- 1
winning_board <- numeric()
last_board <- numeric()

while (bingo_check) {
  bingo_call <- bingo_numbers[i]
  
  for (j in seq_along(l_d_2)) {
    ## Update values to 0 that are called
    l_d_2[[j]] <-
      l_d_2[[j]] %>% 
      mutate(
        across(
          .fns = ~ ifelse(
            test = .x == bingo_call,
            yes = 0,
            no = .x
          )
        )
      )
    
    if (any(colSums(l_d_2[[j]]) == 0 | rowSums(l_d_2[[j]]) == 0)) {
      if (!j %in% winning_board) {
        winning_board[length(winning_board) + 1] <- j
      }
    }
    
    if (length(winning_board) == length(l_d_2)) {
      bingo_check <- FALSE
      last_bard <- j
      break
    }
  }
  
  i <- i + 1
}

last_board <- l_d_2[winning_board[length(winning_board)]]

last_board
## 
## >[1]>
## [[1]]
## # A tibble: 5 x 5
##   col_1 col_2 col_3 col_4 col_5
##       
## 1     0    32     0     0     0
## 2     0     0     0     0    82
## 3     0     0    97     0     0
## 4     0     0     0     0     0
## 5     0     0     0    65     0
(bingo_sum <- sum(unlist(last_board)))
## [1] 276
bingo_call * bingo_sum
## [1] 16836

Reproducibility Receipt

Time Info

[1] "2021-12-20 14:51:53 UTC"


Repo Info

Local:    main C:/Users/harr44107/Documents/projects/advent_of_code_2021
Remote:   main @ origin (https://github.com/KoderKow/advent_of_code_2021.git)
Head:     [f2e6744] 2021-12-16: add github header


Session Info

- Session info ---------------------------------------------------------------
 setting  value                       
 version  R version 4.1.1 (2021-08-10)
 os       Windows 10 x64              
 system   x86_64, mingw32             
 ui       RTerm                       
 language (EN)                        
 collate  English_United States.1252  
 ctype    English_United States.1252  
 tz       UTC                         
 date     2021-12-20                  

- Packages -------------------------------------------------------------------
 package     * version date       lib
 assertthat    0.2.1   2019-03-21 [1]
 backports     1.2.1   2020-12-09 [1]
 bit           4.0.4   2020-08-04 [1]
 bit64         4.0.5   2020-08-30 [1]
 bookdown      0.24    2021-09-02 [1]
 broom         0.7.10  2021-10-31 [1]
 bslib         0.3.1   2021-10-06 [1]
 cellranger    1.1.0   2016-07-27 [1]
 cli           3.0.1   2021-07-17 [1]
 clipr         0.7.1   2020-10-08 [1]
 codetools     0.2-18  2020-11-04 [2]
 colorspace    2.0-2   2021-06-24 [1]
 crayon        1.4.1   2021-02-08 [1]
 DBI           1.1.1   2021-01-15 [1]
 dbplyr        2.1.1   2021-04-06 [1]
 desc          1.4.0   2021-09-28 [1]
 details     * 0.2.1   2020-01-12 [1]
 digest        0.6.28  2021-09-23 [1]
 dplyr       * 1.0.7   2021-06-18 [1]
 ellipsis      0.3.2   2021-04-29 [1]
 evaluate      0.14    2019-05-28 [1]
 fansi         0.5.0   2021-05-25 [1]
 fastmap       1.1.0   2021-01-25 [1]
 forcats     * 0.5.1   2021-01-27 [1]
 fs            1.5.0   2020-07-31 [1]
 generics      0.1.0   2020-10-31 [1]
 ggplot2     * 3.3.5   2021-06-25 [1]
 git2r         0.29.0  2021-11-22 [1]
 glue          1.4.2   2020-08-27 [1]
 gtable        0.3.0   2019-03-25 [1]
 haven         2.4.3   2021-08-04 [1]
 hms           1.1.1   2021-09-26 [1]
 htmltools     0.5.2   2021-08-25 [1]
 httr          1.4.2   2020-07-20 [1]
 jquerylib     0.1.4   2021-04-26 [1]
 jsonlite      1.7.2   2020-12-09 [1]
 knitr         1.36    2021-09-29 [1]
 knitrhooks    0.0.4   2021-12-20 [1]
 lattice       0.20-44 2021-05-02 [2]
 lifecycle     1.0.1   2021-09-24 [1]
 lubridate     1.8.0   2021-10-07 [1]
 magrittr      2.0.1   2020-11-17 [1]
 modelr        0.1.8   2020-05-19 [1]
 munsell       0.5.0   2018-06-12 [1]
 pillar        1.6.4   2021-10-18 [1]
 pkgconfig     2.0.3   2019-09-22 [1]
 png           0.1-7   2013-12-03 [1]
 purrr       * 0.3.4   2020-04-17 [1]
 R6            2.5.1   2021-08-19 [1]
 Rcpp          1.0.7   2021-07-07 [1]
 readr       * 2.0.2   2021-09-27 [1]
 readxl        1.3.1   2019-03-13 [1]
 reprex        2.0.1   2021-08-05 [1]
 rlang         0.4.12  2021-10-18 [1]
 rmarkdown     2.11    2021-09-14 [1]
 rmdformats    1.0.3   2021-10-06 [1]
 rprojroot     2.0.2   2020-11-15 [1]
 rstudioapi    0.13    2020-11-12 [1]
 rvest         1.0.2   2021-10-16 [1]
 sass          0.4.0   2021-05-12 [1]
 scales        1.1.1   2020-05-11 [1]
 sessioninfo   1.1.1   2018-11-05 [1]
 stringi       1.7.5   2021-10-04 [1]
 stringr     * 1.4.0   2019-02-10 [1]
 tibble      * 3.1.6   2021-11-07 [1]
 tidyr       * 1.1.4   2021-09-27 [1]
 tidyselect    1.1.1   2021-04-30 [1]
 tidyverse   * 1.3.1   2021-04-15 [1]
 tzdb          0.1.2   2021-07-20 [1]
 utf8          1.2.2   2021-07-24 [1]
 vctrs         0.3.8   2021-04-29 [1]
 vroom         1.5.5   2021-09-14 [1]
 withr         2.4.2   2021-04-18 [1]
 xfun          0.27    2021-10-18 [1]
 xml2          1.3.2   2020-04-23 [1]
 yaml          2.2.1   2020-02-01 [1]
 zoo         * 1.8-9   2021-03-09 [1]
 source                                    
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 CRAN (R 4.1.1)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 Github (nathaneastwood/knitrhooks@0996563)
 CRAN (R 4.1.1)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            
 RSPM (R 4.1.0)                            

[1] C:/Users/harr44107/Documents/R/win-library/4.1
[2] C:/Program Files/R/R-4.1.1/library