My 2022 Attempts

Day 1

Part 1

library(tidyverse)

input <- read_csv(here::here("2022", "day_01", "input_day01.txt"), 
                  col_names = "calories", skip_empty_rows = FALSE)

input |> 
  mutate(empty = ifelse(is.na(calories), 1, 0),
         elf = cumsum(empty)) |> 
  drop_na() |> 
  group_by(elf) |> 
  summarise(total_calories = sum(calories)) |>
  slice_max(total_calories) |> 
  pull(total_calories) |> 
  print()
[1] 72602
0.338 sec elapsed

Part 2

library(tidyverse)

input <- read_csv(here::here("2022", "day_01", "input_day01.txt"), 
                  col_names = "calories", skip_empty_rows = FALSE)

input |> 
  mutate(empty = ifelse(is.na(calories), 1, 0),
         elf = cumsum(empty)) |> 
  drop_na() |> 
  group_by(elf) |> 
  summarise(total_calories = sum(calories)) |>
  slice_max(total_calories, n = 3) |> 
  summarise(total_calories = sum(total_calories)) |> 
  pull(total_calories) |> 
  print()
[1] 207410
0.109 sec elapsed

Day 2

Didn’t have much time, so all I managed in the time was a series of case_when()’s. If I revisit I might use matrices instead.

Part 1

library(tidyverse)

input <- read_table(here::here("2022", "day_02", "input_day02.txt"), 
                    col_names = c("x", "y"))

input |> 
  rename(opp = x,
         me = y) |> 
  mutate(opp_base_score = case_when(opp == "A" ~ 1,
                                    opp == "B" ~ 2,
                                    opp == "C" ~ 3),
         me_base_score = case_when(me == "X" ~ 1,
                                   me == "Y" ~ 2,
                                   me == "Z" ~ 3),
         score_diff = me_base_score - opp_base_score,
         me_turn_score = case_when(score_diff == -1 | score_diff == 2 ~ 0,
                                   score_diff == 0 ~ 3,
                                   score_diff == 1 | score_diff == -2 ~ 6),
         me_game_score = me_base_score + me_turn_score) |> 
  summarise(total_score = sum(me_game_score)) |> 
  pull(total_score) |> 
  print()
[1] 14531
0.044 sec elapsed

Part 2

library(tidyverse)

input <- read_table(here::here("2022", "day_02", "input_day02.txt"), 
                    col_names = c("x", "y"))

input |> 
  rename(opp = x,
         outcome = y) |> 
  mutate(opp_base_score = case_when(opp == "A" ~ 1,
                                    opp == "B" ~ 2,
                                    opp == "C" ~ 3),
         me_turn_score = case_when(outcome == "X" ~ 0,
                                   outcome == "Y" ~ 3,
                                   outcome == "Z" ~ 6),
         me_base_score = case_when(me_turn_score == 3 ~ opp_base_score,
                                   me_turn_score == 0 & 
                                     opp_base_score > 1 ~ opp_base_score - 1,
                                   me_turn_score == 0 & opp_base_score == 1 ~ 3,
                                   me_turn_score == 6 & 
                                     opp_base_score < 3 ~ opp_base_score + 1,
                                   me_turn_score == 6 & opp_base_score == 3 ~ 1),
         me_game_score = me_turn_score + me_base_score) |> 
  summarise(total_score = sum(me_game_score)) |> 
  pull(total_score) |> 
  print()
[1] 11258
0.037 sec elapsed

Day 3

Would have made for a nice exercise in Python, but who doesn’t love a good regex challenge? 😊

Part 1

library(tidyverse)

input <- read_table(here::here("2022", "day_03", "input_day03.txt"), 
                    col_names = "rucksack")

priority_values <- tibble(char = c(letters, LETTERS)) |> 
  mutate(priority = seq(n()))

input |> 
  mutate(nitems = nchar(rucksack),
         comp1 = str_sub(rucksack, 1, nitems/2),
         comp2 = str_sub(rucksack, nitems/2 + 1, nitems),
         comp1_regex = map_chr(strsplit(comp1, ""), str_c, collapse = "|"),
         common = str_extract(comp2, comp1_regex)) |> 
  left_join(priority_values, by = c("common" = "char")) |> 
  summarise(sum = sum(priority)) |> 
  pull(sum) |> 
  print()
[1] 7793
0.051 sec elapsed

Part 2

library(tidyverse)

input <- read_table(here::here("2022", "day_03", "input_day03.txt"), 
                    col_names = "rucksack")

priority_values <- tibble(char = c(letters, LETTERS)) |> 
  mutate(priority = seq(n()))

input |> 
  mutate(group = rep(seq(unique(n())/3), each = 3)) |> 
  group_by(group) |> 
  summarise(group_items = str_c(rucksack, collapse = "-")) |> 
  separate(group_items, into = c("comp1", "comp2", "comp3")) |> 
  mutate(comp1_regex = map_chr(strsplit(comp1, ""), str_c, collapse = "|"),
         common_12 = str_extract_all(comp2, comp1_regex),
         comp12_regex = map_chr(common_12, str_c, collapse = "|"),
         common_all = str_extract(comp3, comp12_regex)) |> 
  left_join(priority_values, by = c("common_all" = "char")) |> 
  summarise(sum = sum(priority)) |> 
  pull(sum) |> 
  print()
[1] 2499
0.055 sec elapsed

Day 4

Part 1

library(tidyverse)

input <- read_table(here::here("2022", "day_04", "input_day04.txt"), 
                    col_names = "pairs")

input |> 
  separate(pairs, sep = ",|\\-", into = c("section1_start","section1_end", 
                                      "section2_start", "section2_end")) |> 
  mutate(across(everything(), ~ as.numeric(.x)),
         overlap_1_2 = section1_start >= section2_start & 
           section1_end <= section2_end,
         overlap_2_1 = section2_start >= section1_start & 
           section2_end <= section1_end) |> 
  filter(overlap_1_2 | overlap_2_1) |>
  nrow() |> 
  print()
[1] 453
0.112 sec elapsed

Part 2

library(tidyverse)

input <- read_table(here::here("2022", "day_04", "input_day04.txt"), 
                    col_names = "pairs")

input |> 
  separate(pairs, sep = ",|\\-", into = c("section1_start","section1_end", 
                                      "section2_start", "section2_end")) |> 
  mutate(across(everything(), ~ as.numeric(.x)),
         section1 = map2(section1_start, section1_end, ~seq(.x,.y)),
         section2 = map2(section2_start, section2_end, ~seq(.x,.y)),
         intersect = map2(section1, section2, ~ intersect(.x, .y)),
         n_overlapping = lengths(intersect)) |>
  filter(n_overlapping > 0) |> 
  nrow() |> 
  print()
[1] 919
0.079 sec elapsed

Day 5

Took some help from Anthony Durrant here, this one was difficult!

Part 1

library(tidyverse)

crates <- read_fwf(here::here("2022", "day_05", "input_day05.txt"), 
                   col_positions = fwf_widths(widths = NA)) |> 
  janitor::clean_names() |> 
  filter(str_detect(x1, "\\[")) |> 
  separate(x1,
           into = str_glue("stack_{seq(9)}"), 
           sep = c(seq(from = 4, to = 37, by = 4))) |> 
  mutate(across(everything(), ~ str_extract(.x, "[A-Z]"))) |> 
  as.list() |> 
  map(~ .x[grepl("[A-Z]", .x)])

steps <- read_delim(here::here("2022", "day_05", "input_day05.txt"), skip = 10,
                    col_names = c("action", "index", "f", "from", "t", "to")) |> 
  select(index, from, to) |> 
  mutate(across(c(from, to), ~ str_c("stack_", .x)))

rearrange_crates <- function(x, steps){
  from <- steps$from
  to <- steps$to
  n <- steps$index
  
  for(i in seq(n)) {  
    x[[to]] <- c(x[[from]][1], x[[to]])
    x[[from]]<- tail(x[[from]], length(x[[from]])-1)
  }
  return(x)
}

reduce(rlist::list.parse(steps), rearrange_crates, .init = crates) |> 
  map_chr(~ .x[1]) |> 
  paste(collapse = "") |> 
  print()
[1] "WHTLRMZRC"
0.365 sec elapsed

Part 2

library(tidyverse)

crates <- read_fwf(here::here("2022", "day_05", "input_day05.txt"), 
                   col_positions = fwf_widths(widths = NA)) |> 
  janitor::clean_names() |> 
  filter(str_detect(x1, "\\[")) |> 
  separate(x1,
           into = str_glue("stack_{seq(9)}"), 
           sep = c(seq(from = 4, to = 37, by = 4))) |> 
  mutate(across(everything(), ~ str_extract(.x, "[A-Z]"))) |> 
  as.list() |> 
  map(~ .x[grepl("[A-Z]", .x)])

steps <- read_delim(here::here("2022", "day_05", "input_day05.txt"), skip = 10,
                    col_names = c("action", "index", "f", "from", "t", "to")) |> 
  select(index, from, to) |> 
  mutate(across(c(from, to), ~ str_c("stack_", .x)))

rearrange_crates_pt2 <- function(x, steps){
  from <- steps$from
  to <- steps$to
  n <- steps$index
  
  x[[to]] <- c(x[[from]][seq(n)], x[[to]])
  x[[from]]<- tail(x[[from]], length(x[[from]])-n)
  return(x)
}

reduce(rlist::list.parse(steps), rearrange_crates_pt2, .init = crates) |> 
  map_chr(~ .x[1]) |> 
  paste(collapse = "") |> 
  print()
[1] "GMPMLWNMG"
0.156 sec elapsed

Day 6

Actually one of the first ones without any {tidyverse} functions!

Part 1

input <- readLines(here::here("2022", "day_06", "input_day06.txt"))

strsplit(input, split = "")[[1]] |> 
  slider::slide_lgl(~ length(.x) == 4 & length(.x) == length(unique(.x)), 
                    .before = 3) |> 
  (\(x) {which(x == TRUE)[1]})() |> 
  print()
[1] 1300
0.057 sec elapsed

Part 2

input <- readLines(here::here("2022", "day_06", "input_day06.txt"))

strsplit(input, split = "")[[1]] |> 
  slider::slide_lgl(~ length(.x) == 14 & length(.x) == length(unique(.x)), 
                    .before = 13) |> 
  (\(x) {which(x == TRUE)[1]})() |> 
  print()
[1] 3986
0.036 sec elapsed

Day 7

First Python solution this year, with some help from Viliam Pucik

Part 1

from collections import defaultdict
from itertools import accumulate

lines = open('./2022/day_07/input_day07.txt').read().splitlines()

dirs = defaultdict(int)

for line in lines:
  match line.split():
    case "$", "cd", "/":
      path = ["/"]
    case "$", "cd", "..":
      path.pop()
    case "$", "cd", dir:
      path.append(dir + "/")
    case "$" | "dir", *_:
      continue
    case size, _:
      for p in accumulate(path):
        dirs[p] += int(size)

total_sizes = sum(size for size in dirs.values() if size <= 1e5)
print(total_sizes)
1783610
0.019 seconds elapsed

Part 2

from collections import defaultdict
from itertools import accumulate

lines = open('./2022/day_07/input_day07.txt').read().splitlines()

dirs = defaultdict(int)

for line in lines:
  match line.split():
    case "$", "cd", "/":
      path = ["/"]
    case "$", "cd", "..":
      path.pop()
    case "$", "cd", dir:
      path.append(dir + "/")
    case "$" | "dir", *_:
      continue
    case size, _:
      for p in accumulate(path):
        dirs[p] += int(size)

dir_to_remove = min(size for size in dirs.values() if size >= dirs["/"] - 40e6)
print(dir_to_remove)
4370655
0.017 seconds elapsed

Day 8

For-loops just feel more appropriate in Python, with help from nitekat

Part 1

lines = open('./2022/day_08/input_day08.txt').read().splitlines()

trees = [[*map(int, line)] for line in lines]

n = 2 * (len(trees[0]) + len(trees) - 2)

for y in range(1, len(trees) - 1):
  for x in range(1, len(trees[0]) - 1):
    tree = trees[y][x]
    
    row = trees[y]
    col = [i[x] for i in trees]
    
    left = row[:x]
    right = row[x + 1 :]
    top = col[:y]
    bottom = col[y + 1 :]
    
    if tree > min(max(left), max(right), max(top), max(bottom)):
      n += 1

print(n)
1700
0.123 seconds elapsed

Part 2

lines = open('./2022/day_08/input_day08.txt').read().splitlines()

trees = [[*map(int, line)] for line in lines]

s = 0
w = len(trees[0])
h = len(trees)

for y in range(1, len(trees) - 1):
  for x in range(1, len(trees[0]) - 1):
    t = trees[y][x]
    
    row = trees[y]
    col = [i[x] for i in trees]
    
    left = row[:x][::-1]
    right = row[x + 1 :]
    top = col[:y][::-1]
    bottom = col[y + 1 :]
    
    left_blocked = [i for i, v in enumerate(left) if v - t >= 0]
    left_score = x if len(left_blocked) == 0 else left_blocked[0] + 1
    
    right_blocked = [i for i, v in enumerate(right) if v - t >= 0]
    right_score = w - x - 1 if len(right_blocked) == 0 else right_blocked[0] + 1
    
    top_blocked = [i for i, v in enumerate(top) if v - t >= 0]
    top_score = y if len(top_blocked) == 0 else top_blocked[0] + 1
    
    bottom_blocked = [i for i, v in enumerate(bottom) if v - t >= 0]
    bottom_score = h - y - 1 if len(bottom_blocked) == 0 else bottom_blocked[0] + 1
    
    ss = left_score * right_score * top_score * bottom_score
    if ss > s:
        s = ss

print(s)
470596
0.246 seconds elapsed

Day 9

Day 10

Part 1

library(tidyverse)

input <- read_table(here::here("2022", "day_10", "input_day10.txt"), 
                    col_names = c("operation", "argument"))

input |> 
  replace_na(list(argument = 0)) |> 
  mutate(steps = case_when(str_detect(operation, "add") ~ 2, 
                           str_detect(operation, "noop") ~ 1),
         step_num_start = tail(accumulate(steps, `+`, .init = 1), -1) - steps,
         x_reg = 1 + cumsum(argument),
         x_reg_prev = c(1, head(x_reg, -1))) |> 
  uncount(steps) |> 
  rowid_to_column(var = "step_num") |> 
  select(step_num, x_reg_prev) |>
  rename(x_reg = x_reg_prev) |> 
  filter(step_num %in% seq(20, n(), 40)) |> 
  summarise(total = sum(step_num * x_reg)) |> 
  pull(total) |> 
  print()
[1] 14060
0.048 sec elapsed

Part 2

library(tidyverse)

input <- read_table(here::here("2022", "day_10", "input_day10.txt"), 
                    col_names = c("operation", "argument"))

input |> 
  replace_na(list(argument = 0)) |> 
  mutate(steps = case_when(str_detect(operation, "add") ~ 2, 
                           str_detect(operation, "noop") ~ 1),
         step_num_start = tail(accumulate(steps, `+`, .init = 1), -1) - steps,
         x_reg = 1 + cumsum(argument),
         x_reg_prev = c(1, head(x_reg, -1))) |> 
  uncount(steps) |> 
  mutate(step_num = seq(1, n())) |>
  select(step_num, x_reg_prev) |>
  rename(x_reg = x_reg_prev) |> 
  mutate(x_pos = (step_num - 1) %% 40,
         pixel_on = abs(x_pos - x_reg) < 2,
         pixel = ifelse(pixel_on, "#", NA),
         row_num = cumsum(x_pos == 0)) |> 
  group_by(row_num) |> 
  mutate(x = row_number()) |> 
  filter(pixel_on) |> 
  ggplot(aes(x = x, y = row_num)) +
  geom_tile(fill = "#f2f2f2") +
  geom_text(label = "#", color = "#b3b3b3", size = 4) +
  scale_y_reverse() +
  coord_equal() + 
  theme_void() + 
  theme(plot.margin = margin(rep(10,4), unit = "mm"),
        plot.background = element_rect(fill = "#0f0f23"))

ggsave(here::here("2022", "day_10", "plot_day10_pt2.png"), last_plot(), 
       height = 3, width = 8, dpi = 300)
0.39 sec elapsed

plot_day10_2022

Day 11

Day 12

Day 13

Day 14

Day 15

Day 16

Day 17

Day 18

Day 19

Day 20

Day 21

Day 22

Day 23

Day 24

Day 25