library(tidyverse)
library(here)
library(arrow)
Let’s just say this puzzle made my processor go BRRRRRRRRRRRRR.
What is the lowest location number that corresponds to any of the initial seed numbers?
The idea of this puzzle is that they provided specific instructions in the puzzle input that allows us to construct the conversion tables need to convert from seed to location. The conversion tables are used to convert the seed numbers to soil, then soil to fertilizer, then fertilizer to water, then water to light, then light to temp, then temp to humidity, then finally humidity to location.
I don’t have the most efficient method of doing this, but it works. The strategy of this puzzle isn’t very difficulty, however the sheer amount of data that needs to be processed is what makes this puzzle difficult. Each conversion table that being generated are in the hundreds of millions of rows, and there are 7 conversion tables that need to be generated for us to convert from seed to location. My strategy was to use the arrow package, which allows for out of memory processing of big data.
Part 1
We first read in the puzzle prompt, and extract out the specific instructions for each conversion table into its own data frame. We create two helper functions that helps us process the data. The first function generate_map_conversion_data
, takes in the conversion table data, and the title of the conversion table, and returns a list of arrow tables that contains the conversion table data. The second function takes in a list of arrow tables, and the source numbers, and returns the destination numbers.
<- read_lines(
data here('posts', 'aoc-2023-d5', 'puzzle-input.txt')
)
<- data[1] |>
seeds str_remove('seeds: ') |>
str_split(pattern = ' ') |>
unlist() |>
as.numeric()
<- data[4:50]
seed_to_soil_map <- data[53:70]
soil_to_fertilizer_map <- data[73:84]
fertilizer_to_water_map <- data[87:135]
water_to_light_map <- data[138:167]
light_to_temp_map <- data[170:192]
temp_to_humidity_map <- data[195:237]
humidity_to_location_map
<- \(map_data, title) {
generate_map_conversion_data <- as_tibble(map_data) |>
map_data separate(value, c('destination', 'origin', 'range'), sep = ' ') |>
mutate(across(everything(), \(x) as.numeric(x)))
<- pmap(map_data, \(destination, origin, range) {
table arrow_table(
origin = seq(origin, origin + range - 1, by = 1),
destination = seq(destination, destination + range - 1, by = 1)
)
.progress = glue::glue('Constructing Conversion Table for {title}:'))
},
<- concat_tables(!!!table)
table
}
<-
extract_map_conversion_data
\(map_data, origin_values, title) {
<- generate_map_conversion_data(map_data, title)
map_data
<- map_data |>
map_data filter(origin %in% origin_values) |>
collect()
<- map_data |> pull(origin)
origin
<- setdiff(origin_values, origin)
missing
if (length(missing) > 0) {
<- tibble(origin = missing,
map_data destination = missing) |>
bind_rows(map_data)
}
map_data }
Here we generate a tibble that contains the conversion table data, and the title of the conversion table.
<- tibble(
parameters title = c(
'Seed to Soil',
'Soil to Fertilizer',
'Fertilizer to Water',
'Water to Light',
'Light to Temp',
'Temp to Humidity',
'Humidity to Location'
),data = list(
seed_to_soil_map,
soil_to_fertilizer_map,
fertilizer_to_water_map,
water_to_light_map,
light_to_temp_map,
temp_to_humidity_map,
humidity_to_location_map
)
)
parameters
# A tibble: 7 × 2
title data
<chr> <list>
1 Seed to Soil <chr [47]>
2 Soil to Fertilizer <chr [18]>
3 Fertilizer to Water <chr [12]>
4 Water to Light <chr [49]>
5 Light to Temp <chr [30]>
6 Temp to Humidity <chr [23]>
7 Humidity to Location <chr [43]>
We then use the pwalk
function to iterate through the list of conversion tables, and extract the destination numbers from the conversion tables. We then use the pull
function to extract the destination numbers from the arrow table, and assign it to the origin
variable. This iterates through the list of conversion tables, and extracts the destination numbers from each conversion table, from seed to eventually location.
<- seeds
origin pwalk(parameters, \(title, data) {
<- extract_map_conversion_data(
out
data, origin, title
)
<<- out |> pull(destination)
origin
return(out)
.progress = 'Extracting Destination Data:') },
We then use the min
function to find the lowest location number that corresponds to any of the initial seed numbers.
|> min() origin
Reuse
Citation
@online{luu2023,
author = {Luu, Michael},
title = {Advent of {Code} 2023, {Day} 5},
date = {2023-12-06},
langid = {en}
}