Advent of Code 2023, Day 4

advent of code
Author

Michael Luu

Published

December 5, 2023

Part 1

library(tidyverse)
library(here)

The complexity of this puzzle dropped a bit for Day 4. Definitely wasn’t as difficulty as Day 3.

Let’s again take a look at the prompt for the puzzle

Take a seat in the large pile of colorful cards. How many points are they worth in total?

The idea is that we have a whole bunch of scratch cards, with a set of winning numbers and your set of numbers. We need to identify the total number of matches for each card, and then calculate the points for each card.

We calculate the points by using the following formula.

  • If there are no matches then the card is worth 0 points
  • If there are 1 match then the card is worth 1 point
  • If there are more than 1 match, then the card is worth 2 times the number of matches

Let’s first read in the data

data <- read_lines(
  here('posts', 'aoc-2023-d4', 'puzzle-input.txt')
)

data <- as_tibble(data)

data
# A tibble: 196 × 1
   value                                                                        
   <chr>                                                                        
 1 Card   1: 61 73 92 28 96 76 32 62 44 53 | 61 17 26 13 92  5 73 29 53 42 62 4…
 2 Card   2:  3 88 36 12  2  9 15 55 21 89 | 23 39 98 36  2 24  9  3 78 95 55 3…
 3 Card   3: 96 44 52 56 82 89 73 50  9 68 | 39 71 64 32 13 57 56 67 34 84 51 5…
 4 Card   4: 54 84 76 44 38 33 12 17 93 94 | 18 21 53 11  7 98 78 92  9 32 29 5…
 5 Card   5:  8 11 33 98 37 80 39 76 53 91 | 82 35 27 29 50 73 24  4  5 53 93 6…
 6 Card   6: 10 58 39 28 35 79 14 73 64 96 | 90 86 38 93 74 29 21 14 33 16 85  …
 7 Card   7:  1 96 73 38 64 87 45 25 99 10 | 11 30 96 43 17 72 24 55 79 64 98 4…
 8 Card   8: 24  3 23 50 58 35 57 51 22  2 | 95 50 22 75 27 57 72 25 12 61 82 1…
 9 Card   9: 98 59 30 22 10 69 68 17 48  8 | 22 75 34 63  7 72 30 73 19 13 35 8…
10 Card  10: 82 32 48 60 17 85 97 22 26 87 | 33 49 81 29 70  8 74 45 97 68 36 7…
# ℹ 186 more rows

Now that the data is read in, let’s tidy the data up a bit. We’ll use the separate function to split the data into the card and the value. We’ll then use str_extract to extract the card number from the card string. We’ll then use separate again to split the value into the winning numbers and the elf’s numbers. We’ll then use str_split to split the winning numbers and elf’s numbers into a list of numbers. We’ll then use as.numeric to convert the numbers from strings to numbers. We’ll then use na.omit to remove any NA values from the list of numbers.

data <- data |>
  separate(value, c('card', 'value'), sep = ': ') |>
  mutate(card = str_extract(card, '\\d+') |> as.numeric()) |>
  separate(value, c('winning_numbers', 'elfs_numbers'), sep = ' \\| ') |>
  mutate(winning_numbers = str_split(winning_numbers, ' ') |>
           map(\(x) as.numeric(x)),) |>
  mutate(winning_numbers = map(winning_numbers, \(x) na.omit(x)))

data <- data |> 
  mutate(
    elfs_numbers = str_split(elfs_numbers, ' '),
    elfs_numbers = map(elfs_numbers, \(x) as.numeric(x) |> na.omit())
  )

data
# A tibble: 196 × 3
    card winning_numbers elfs_numbers
   <dbl> <list>          <list>      
 1     1 <dbl [10]>      <dbl [25]>  
 2     2 <dbl [10]>      <dbl [25]>  
 3     3 <dbl [10]>      <dbl [25]>  
 4     4 <dbl [10]>      <dbl [25]>  
 5     5 <dbl [10]>      <dbl [25]>  
 6     6 <dbl [10]>      <dbl [25]>  
 7     7 <dbl [10]>      <dbl [25]>  
 8     8 <dbl [10]>      <dbl [25]>  
 9     9 <dbl [10]>      <dbl [25]>  
10    10 <dbl [10]>      <dbl [25]>  
# ℹ 186 more rows

Now that the data is tidied up, let’s calculate the number of matches for each card. We’ll use the intersect function to calculate the number of matches. We’ll then use length to calculate the number of matches. We’ll then use map_int to calculate the points for each card, based on the above rule.

calculate_matches <- \(winning_numbers, elfs_numbers) {
  intersect(elfs_numbers, winning_numbers) |>
    length()
  
}

data <- data |> 
  rowwise() |> 
  mutate(
    matches = calculate_matches(winning_numbers, elfs_numbers)
  ) |> 
  ungroup()

data <- data |>
  mutate(points = map_int(matches, \(matches) {
    if (matches == 0) {
      points <- 0
    } else if (matches == 1) {
      points <- 1
    } else if (matches > 1) {
      points <- 2 ^ (matches - 1)
    }
    
    return(points)
  }))

data
# A tibble: 196 × 5
    card winning_numbers elfs_numbers matches points
   <dbl> <list>          <list>         <int>  <int>
 1     1 <dbl [10]>      <dbl [25]>        10    512
 2     2 <dbl [10]>      <dbl [25]>        10    512
 3     3 <dbl [10]>      <dbl [25]>         1      1
 4     4 <dbl [10]>      <dbl [25]>         1      1
 5     5 <dbl [10]>      <dbl [25]>         2      2
 6     6 <dbl [10]>      <dbl [25]>         3      4
 7     7 <dbl [10]>      <dbl [25]>        10    512
 8     8 <dbl [10]>      <dbl [25]>        10    512
 9     9 <dbl [10]>      <dbl [25]>         5     16
10    10 <dbl [10]>      <dbl [25]>         2      2
# ℹ 186 more rows

Finally we just add up the points, and we have the answer

sum(data$points)

Reuse

Citation

BibTeX citation:
@online{luu2023,
  author = {Luu, Michael},
  title = {Advent of {Code} 2023, {Day} 4},
  date = {2023-12-05},
  langid = {en}
}
For attribution, please cite this work as:
Luu, Michael. 2023. “Advent of Code 2023, Day 4.” December 5, 2023.