library(vctrs)
library(tidyverse)
Day 3
Advent of Code: Worked Solutions
Setup
Import libraries:
Read input from file:
<- read_lines("../input/day03.txt") input
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):
<- \(x) vec_count(x) |> slice_max(count) |> pull(key) |> max()
most_common <- \(x) vec_count(x) |> slice_min(count) |> pull(key) |> min() least_common
Define a function to convert a vector of binary integers to a decimal number:
<- \(x) strtoi(str_flatten(x), base = 2) bin_to_num
Prep the input by splitting binary numbers into separate digits by positions:
<- input |>
df 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:
<- function(data, f = c("most_common", "least_common")) {
get_rating
for (i in unique(data$pos)) {
<- data |>
id_lst filter(pos == i) |>
filter(value == get(f)(value)) |>
pull(id)
<- filter(data, id %in% id_lst)
data
if (length(id_lst) == 1)
return(bin_to_num(data$value))
}
}
<- partial(get_rating, f = "most_common")
oxygen_rating <- partial(get_rating, f = "least_common") co2_rating
Compute the final life support rating:
oxygen_rating(df) * co2_rating(df)