1 Setup
1.1 Libraries
library(httr)
library(xml2)
library(magrittr)
library(dplyr)
library(purrr)
library(stringr)
1.2 Retrieve Data from AoC
session_cookie <- set_cookies(session = keyring::key_get("AoC-GitHub-Cookie"))
base_url <- paste0("https://adventofcode.com/", params$year, "/day/", params$task_nr)
puzzle <- GET(base_url,
session_cookie) %>%
content(encoding = "UTF-8") %>%
xml_find_all("///article") %>%
lapply(as.character)
parse_puzzle_data <- function(text_block = readClipboard()) {
if (length(text_block) == 1L) {
text_block <- text_block %>%
str_split("\n") %>%
extract2(1L) %>%
keep(nzchar)
}
text_block %>%
str_split(",") %>%
extract2(1L) %>%
as.integer()
}
puzzle_data <- local({
GET(paste0(base_url, "/input"),
session_cookie) %>%
content(encoding = "UTF-8") %>%
parse_puzzle_data()
})
2 Puzzle Day 15
2.1 Part 1
2.1.1 Description
— Day 15: Rambunctious Recitation —
You catch the airport shuttle and try to book a new flight to your vacation island. Due to the storm, all direct flights have been cancelled, but a route is available to get around the storm. You take it.
While you wait for your flight, you decide to check in with the Elves back at the North Pole. They’re playing a memory game and are ever so excited to explain the rules!
In this game, the players take turns saying numbers. They begin by taking turns reading from a list of starting numbers (your puzzle input). Then, each turn consists of considering the most recently spoken number:
-
If that was the first time the number has been spoken, the current player says
0. - Otherwise, the number had been spoken before; the current player announces how many turns apart the number is from when it was previously spoken.
So, after the starting numbers, each turn results in that player speaking aloud either 0 (if the last number is new) or an age (if the last number is a repeat).
For example, suppose the starting numbers are 0,3,6:
-
Turn 1: The
1st number spoken is a starting number,0. -
Turn 2: The
2nd number spoken is a starting number,3. -
Turn 3: The
3rd number spoken is a starting number,6. -
Turn 4: Now, consider the last number spoken,
6. Since that was the first time the number had been spoken, the4th number spoken is0. -
Turn 5: Next, again consider the last number spoken,
0. Since it had been spoken before, the next number to speak is the difference between the turn number when it was last spoken (the previous turn,4) and the turn number of the time it was most recently spoken before then (turn1). Thus, the5th number spoken is4 - 1,3. -
Turn 6: The last number spoken,
3had also been spoken before, most recently on turns5and2. So, the6th number spoken is5 - 2,3. -
Turn 7: Since
3was just spoken twice in a row, and the last two turns are1turn apart, the7th number spoken is1. -
Turn 8: Since
1is new, the8th number spoken is0. -
Turn 9:
0was last spoken on turns8and4, so the9th number spoken is the difference between them,4. -
Turn 10:
4is new, so the10th number spoken is0.
(The game ends when the Elves get sick of playing or dinner is ready, whichever comes first.)
Their question for you is: what will be the 2020th number spoken? In the example above, the 2020th number spoken will be 436.
Here are a few more examples:
-
Given the starting numbers
1,3,2, the2020th number spoken is1. -
Given the starting numbers
2,1,3, the2020th number spoken is10. -
Given the starting numbers
1,2,3, the2020th number spoken is27. -
Given the starting numbers
2,3,1, the2020th number spoken is78. -
Given the starting numbers
3,2,1, the2020th number spoken is438. -
Given the starting numbers
3,1,2, the2020th number spoken is1836.
Given your starting numbers, what will be the 2020th number spoken?
2.1.2 Solution
We store for each number the round when it was called the last time. If it was never
called we return 0, otherwise the difference to the actual turn.
play_memory <- function(nrs, turns) {
n <- length(nrs)
last_seen <- integer(turns)
## store for each but the last number in the start sequence it's position
## +1 because we also want ot store 0
for (i in seq_len(n - 1L)) {
last_seen[nrs[i] + 1L] <- i
}
## the last number called
last <- nrs[n]
for (turn in n:(turns - 1L)) {
## when did we call the number the last time
prev <- last_seen[last + 1L]
## update the round when the number was called
last_seen[last + 1L] <- turn
if (prev == 0L) {
## if the number was never called: 0 is the next number
last <- 0L
} else {
## otherwise the difference between last round and the previous time
last <- turn - prev
}
}
last
}
play_memory(puzzle_data, 2020L)
## [1] 249
2.2 Part 2
2.2.1 Description
— Part Two —
Impressed, the Elves issue you a challenge: determine the 30000000th number spoken. For example, given the same starting numbers as above:
-
Given
0,3,6, the30000000th number spoken is175594. -
Given
1,3,2, the30000000th number spoken is2578. -
Given
2,1,3, the30000000th number spoken is3544142. -
Given
1,2,3, the30000000th number spoken is261214. -
Given
2,3,1, the30000000th number spoken is6895259. -
Given
3,2,1, the30000000th number spoken is18. -
Given
3,1,2, the30000000th number spoken is362.
Given your starting numbers, what will be the 30000000th number spoken?
2.2.2 Solution
We simply need to call the function with a larger turn count as it is reasonable fast.
play_memory(puzzle_data, 3e7)
## [1] 41687