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.261 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.084 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.038 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.021 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.046 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.043 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.043 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.071 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.371 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.143 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.046 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.027 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.013 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.010 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.092 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.203 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.039 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.342 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