library(vctrs)
library(tidyverse)Day 3
Advent of Code: Worked Solutions
Setup
Import libraries:
Read input from file:
input <- read_lines("../input/day03.txt")Part 1
Define functions to compute the least and most common values in a vector (using greatest/least values as tiebreakers, as defined later in part 2):
most_common <- \(x) vec_count(x) |> slice_max(count) |> pull(key) |> max()
least_common <- \(x) vec_count(x) |> slice_min(count) |> pull(key) |> min()Define a function to convert a vector of binary integers to a decimal number:
bin_to_num <- \(x) strtoi(str_flatten(x), base = 2)Prep the input by splitting binary numbers into separate digits by positions:
df <- input |>
str_split("") |>
enframe(name = "id") |>
unnest_longer(value, indices_to = "pos") |>
mutate(value = as.integer(value))Compute the most and least common values in each position to get the gamma and epsilon values, then multiply them together to get the power consumption:
df |>
summarize(
gamma = most_common(value),
epsilon = least_common(value),
.by = pos
) |>
summarize(across(c(gamma, epsilon), bin_to_num)) |>
prod()Part 2
Define a set of functions to compute the oxygen and co2 ratings:
get_rating <- function(data, f = c("most_common", "least_common")) {
for (i in unique(data$pos)) {
id_lst <- data |>
filter(pos == i) |>
filter(value == get(f)(value)) |>
pull(id)
data <- filter(data, id %in% id_lst)
if (length(id_lst) == 1)
return(bin_to_num(data$value))
}
}
oxygen_rating <- partial(get_rating, f = "most_common")
co2_rating <- partial(get_rating, f = "least_common")Compute the final life support rating:
oxygen_rating(df) * co2_rating(df)