Task 12

Thorn Thaler - <

2025-03-20

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 of 6.
  • [[[3]]] and {“a”:{“b”:4},“c”:-1} both have a sum of 3.
  • {“a”:[-1,1]} and [-1,{“a”:1}] both have a sum of 0.
  • [] and {} both have a sum of 0.

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 of 6.
  • [1,{“c”:“red”,“b”:2},3] now has a sum of 4, because the middle object is ignored.
  • {“d”:“red”,“e”:[1,2,3,4],“f”:5} now has a sum of 0, because the entire structure is ignored.
  • [1,“red”,5] has a sum of 6, 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