1 Setup
1.1 Libraries
library(httr)
library(xml2)
library(tibble)
library(magrittr)
library(dplyr)
library(purrr)
library(stringr)
library(stringi)
library(knitr)
library(cli)
library(digest)
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
}
puzzle_data <- local({
GET(paste0(base_url, "/input"),
session_cookie) %>%
content(encoding = "UTF-8") %>%
parse_puzzle_data()
})
2 Puzzle Day 4
2.1 Part 1
2.1.1 Description
— Day 4: The Ideal Stocking Stuffer —
Santa needs help mining some AdventCoins (very similar to bitcoins) to use as gifts for all the economically forward-thinking little girls and boys.
To do this, he needs to find MD5 hashes which, in hexadecimal, start with at least five zeroes. The input to the MD5 hash is some secret key (your puzzle input, given below) followed by a number in decimal. To mine AdventCoins, you must find Santa the lowest positive number (no leading zeroes: 1
, 2
, 3
, …) that produces such a hash.
For example:
-
If your secret key is
abcdef
, the answer is609043
, because the MD5 hash ofabcdef609043
starts with five zeroes (000001dbbfa…
), and it is the lowest such number to do so. -
If your secret key is
pqrstuv
, the lowest number it combines with to make an MD5 hash starting with five zeroes is1048970
; that is, the MD5 hash ofpqrstuv1048970
looks like000006136ef…
.
2.1.2 Solution
If we wanted to create an input, which results in a particular hash the hash function would need to be vulnerable to preimage attacks which MD5 is only theoretically. Thus, we simply opted for a brute force algorithm, checking the smallest number which results in the selected prefix.
find_suffix <- function(secret, nr_zeros, start = 1, end = 1e6) {
target <- rep("0", nr_zeros) %>%
paste(collapse = "")
for (i in start:end) {
msg <- paste0(secret, i)
hash <- digest(msg, "md5", serialize = FALSE)
if (substr(hash, 1, nr_zeros) == target) {
break
}
}
i
}
find_suffix(puzzle_data, 5)
## [1] 117946
2.2 Part 2
2.2.1 Description
— Part Two —
Now find one that starts with six zeroes.
2.2.2 Solution
We use the same idea as before, but now look for a prefix of size 6.
find_suffix(puzzle_data, 6, 1e6, 1e7)
## [1] 3938038