1 Setup
1.1 Libraries
library(httr)
library(xml2)
library(magrittr)
library(purrr)
library(stringr)
library(jsonlite)
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 12
2.1 Part 1
2.1.1 Description
— Day 12: JSAbacusFramework.io —
Santa’s Accounting-Elves need help balancing the books after a recent order. Unfortunately, their accounting software uses a peculiar storage format. That’s where you come in.
They have a JSON document which contains a variety of things: arrays ([1,2,3]
), objects ({“a”:1, “b”:2}
), numbers, and strings. Your first job is to simply find all of the numbers throughout the document and add them together.
For example:
-
[1,2,3]
and{“a”:2,“b”:4}
both have a sum of6
. -
[[[3]]]
and{“a”:{“b”:4},“c”:-1}
both have a sum of3
. -
{“a”:[-1,1]}
and[-1,{“a”:1}]
both have a sum of0
. -
[]
and{}
both have a sum of0
.
You will not encounter any strings containing numbers.
What is the sum of all numbers in the document?
2.1.2 Solution
We rely on exiting JSON parsers to parse the string, then we extract all numbers and sum them up.
sum_numbers <- function(json_data) {
unlist(json_data) %>%
as.integer() %>%
suppressWarnings() %>%
sum(na.rm = TRUE)
}
json_data <- fromJSON(puzzle_data, simplifyVector = FALSE)
sum_numbers(json_data)
## [1] 156366
2.2 Part 2
2.2.1 Description
— Part Two —
Uh oh - the Accounting-Elves have realized that they double-counted everything red.
Ignore any object (and all of its children) which has any property with the value “red”
. Do this only for objects ({…}
), not arrays ([…]
).
-
[1,2,3]
still has a sum of6
. -
[1,{“c”:“red”,“b”:2},3]
now has a sum of4
, because the middle object is ignored. -
{“d”:“red”,“e”:[1,2,3,4],“f”:5}
now has a sum of0
, because the entire structure is ignored. -
[1,“red”,5]
has a sum of6
, because“red”
in an array has no effect.
2.2.2 Solution
We use a recursive function to iterate through the elements. Whenever red
is part of the
elements we do nothing, else we add the numbers to the final results. We jsut have to make
sure that we apply this logic only to JSON objects. To identify whether the original JSON
string was an object or an array, we check whether the slot has names (in this case it was
an object), otherwise it was an array.
sum_filtered_numbers <- function(json_data) {
sum_list <- function(branch) {
is_object <- branch %>%
names() %>%
is.null() %>%
not()
slot_sum <- children_sum <- 0L
if (!is_object || !"red" %in% branch) {
slot_sum <- keep(branch, is.numeric) %>%
unlist() %>%
sum()
children_sum <- keep(branch, is.list) %>%
map_int(sum_list) %>%
sum()
}
slot_sum + children_sum
}
sum_list(json_data)
}
sum_filtered_numbers(json_data)
## [1] 96852