library(tidyverse)Day 4
Advent of Code: Worked Solutions
Setup
Import libraries:
Read input from file:
# List of drawn numbers
drawn <- scan("../input/day04.txt", nlines = 1, sep = ",", quiet = TRUE)
# Set of bingo boards
boards <- read_table("../input/day04.txt", skip = 2, col_names = FALSE) |>
group_split(cumsum(row_number() %% 5 == 1), .keep = FALSE) |>
map(~ unname(as.matrix(.x)))Part 1
For all bingo boards, determine the time at which each number on their card is drawn.
filled <- imap_dfr(boards, \(board, board_id) {
imap_dfr(drawn, \(num, idx) {
which(board == num, arr.ind = TRUE) |>
as_tibble() |>
mutate(
time = idx,
board_id = board_id
)
})
})For each board, determine the time at which each “wins” by achieving a full row or column:
wins <- map_dfr(c("row", "col"), \(dim) {
filled |>
summarize(n = n(), time = max(time), .by = all_of(c("board_id", dim))) |>
rename(dim_value = {{ dim }}) |>
mutate(dim_name = dim) |>
filter(n == 5)
}) |>
summarize(time = min(time), .by = board_id)Define a function to score a board at the time of its win:
score <- function(board_id, time_win) {
board <- boards[[board_id]]
nums_drawn <- drawn[1:time_win]
unmarked <- board[!(board %in% nums_drawn)]
score <- sum(unmarked) * tail(nums_drawn, 1)
return(score)
}Compute the final score of the first board to win:
first_winner <- slice_min(wins, time)
score(first_winner$board_id, first_winner$time)Part 2
Compute the final score of the last board to win:
last_winner <- slice_max(wins, time)
score(last_winner$board_id, last_winner$time)