library(tidyverse)
Day 4
Advent of Code: Worked Solutions
Setup
Import libraries:
Read input from file:
# List of drawn numbers
<- scan("../input/day04.txt", nlines = 1, sep = ",", quiet = TRUE)
drawn
# Set of bingo boards
<- read_table("../input/day04.txt", skip = 2, col_names = FALSE) |>
boards 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.
<- imap_dfr(boards, \(board, board_id) {
filled 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:
<- map_dfr(c("row", "col"), \(dim) {
wins |>
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:
<- function(board_id, time_win) {
score
<- boards[[board_id]]
board <- drawn[1:time_win]
nums_drawn <- board[!(board %in% nums_drawn)]
unmarked <- sum(unmarked) * tail(nums_drawn, 1)
score
return(score)
}
Compute the final score of the first board to win:
<- slice_min(wins, time)
first_winner
score(first_winner$board_id, first_winner$time)
Part 2
Compute the final score of the last board to win:
<- slice_max(wins, time)
last_winner
score(last_winner$board_id, last_winner$time)