Alexander Enge 2022-12-01
- Day 1: Calorie Counting :pizza:
- Day 2: Rock Paper Scissors :scissors:
- Day 3: Rucksack Reorganization 🎒
- Day 4: Camp Cleanup 🧹
- Day 5: Supply Stacks :building_construction:
- Day 6: Tuning Trouble 📻
- Day 7: No Space Left On Device 📁
- Day 8: Treetop Tree House 🌳
Hi! 👋
This repository contains my solutions for the 2022 edition of Advent of Code.
From the Advent of Code website:
Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like. People use them as interview prep, company training, university coursework, practice problems, a speed contest, or to challenge each other.
I’ll be using a mix of Python, Base R, and tidyverse-style R.
max_elf = 0 this_elf = 0 with open('data/day1.txt') as f: for line in f: if this_elf > max_elf: max_elf = this_elf if line == '\n': this_elf = 0 else: this_elf += int(line.strip()) print(max_elf)64929 lines <- readLines("data/day1.txt", warn = FALSE) elf_indices <- cumsum(lines == "") split(lines, elf_indices) |> lapply(as.numeric) |> lapply(sum, na.rm = TRUE) |> unlist() |> max()[1] 64929 max_elves = [0, 0, 0] this_elf = 0 with open('data/day1.txt') as f: for line in f: max_elves.sort() if this_elf > max_elves[0]: max_elves[0] = this_elf if line == '\n': this_elf = 0 else: this_elf += int(line.strip()) print(sum(max_elves))193697 lines <- readLines("data/day1.txt", warn = FALSE) elf_indices <- cumsum(lines == "") split(lines, elf_indices) |> lapply(as.numeric) |> lapply(sum, na.rm = TRUE) |> unlist() |> sort() |> tail(3) |> sum()[1] 193697 library(tidyverse) read_table("data/day2.txt", col_names = c("other", "me")) %>% unite(col = "round", other, me, remove = FALSE) %>% mutate( game_score = case_when( round %in% c("A_Y", "B_Z", "C_X") ~ 6, round %in% c("A_X", "B_Y", "C_Z") ~ 3, round %in% c("A_Z", "B_X", "C_Y") ~ 0 ), play_score = recode(me, "X" = 1, "Y" = 2, "Z" = 3), score = game_score + play_score ) %>% pull(score) %>% sum()[1] 14297 read_table("data/day2.txt", col_names = c("other", "outcome")) %>% unite(col = "round", other, outcome, remove = FALSE) %>% mutate( me = case_when( round %in% c("A_X", "B_Z", "C_Y") ~ "Z", round %in% c("A_Y", "B_X", "C_Z") ~ "X", round %in% c("A_Z", "B_Y", "C_X") ~ "Y" ), game_score = recode(outcome, "X" = 0, "Y" = 3, "Z" = 6), play_score = recode(me, "X" = 1, "Y" = 2, "Z" = 3), score = game_score + play_score ) %>% pull(score) %>% sum()[1] 10498 from string import ascii_lowercase, ascii_uppercase with open('data/day3.txt') as f: lines = [line.strip() for line in f.readlines()] halves = [(line[:len(line) // 2], line[len(line) // 2:]) for line in lines] items = [set(half_1).intersection(half_2).pop() for half_1, half_2 in halves] letters = ascii_lowercase + ascii_uppercase priorities = [letters.index(item) + 1 for item in items] print(sum(priorities))7795 group_size = 3 groups = [lines[ix:ix + group_size] for ix in range(0, len(lines), group_size)] badges = [set.intersection(*map(set, group)).pop() for group in groups] priorities = [letters.index(badge) + 1 for badge in badges] print(sum(priorities))2703 def is_contained(min_1, max_1, min_2, max_2): return (min_1 >= min_2 and max_1 <= max_2 or min_2 >= min_1 and max_2 <= max_1) contained = 0 with open('data/day4.txt') as f: for line in f: elf_1, elf_2 = line.strip().split(',') min_1, max_1 = [int(section) for section in elf_1.split('-')] min_2, max_2 = [int(section) for section in elf_2.split('-')] contained += is_contained(min_1, max_1, min_2, max_2) print(contained)475 read_csv("data/day4.txt", col_names = c("elf_1", "elf_2")) %>% transmute(across(.fns = str_split, pattern = "-")) %>% unnest_wider(c(elf_1, elf_2), names_sep = "_", transform = as.integer) %>% mutate( contained_1 = elf_1_1 >= elf_2_1 & elf_1_2 <= elf_2_2, contained_2 = elf_2_1 >= elf_1_1 & elf_2_2 <= elf_1_2, contained = contained_1 | contained_2 ) %>% pull(contained) %>% sum()[1] 475 def is_overlap(min_1, max_1, min_2, max_2): return (max_1 >= min_2 and max_2 >= min_1) overlaps = 0 with open('data/day4.txt') as f: for line in f: elf_1, elf_2 = line.strip().split(',') min_1, max_1 = [int(section) for section in elf_1.split('-')] min_2, max_2 = [int(section) for section in elf_2.split('-')] overlaps += is_overlap(min_1, max_1, min_2, max_2) print(overlaps)825 read_csv("data/day4.txt", col_names = c("elf_1", "elf_2")) %>% transmute(across(.fns = str_split, pattern = "-")) %>% unnest_wider(c(elf_1, elf_2), names_sep = "_", transform = as.integer) %>% mutate(overlap = elf_1_2 >= elf_2_1 & elf_2_2 >= elf_1_1) %>% pull(overlap) %>% sum()[1] 825 transpose_list <- function(l) as.list(as.data.frame(t(as.data.frame(l)))) drop_empty <- function(x) x[x != " "] input <- read.csv("data/day5.txt", header = FALSE) input_1 <- subset(input, grepl("\\[", V1))$V1 stack_ixs <- seq(2, max(nchar(input_1)), by = 4) stacks <- lapply(input_1, substring, first = stack_ixs, last = stack_ixs) |> rev() |> transpose_list() |> lapply(drop_empty) input_2 <- subset(input, grepl("move", V1))$V1 moves <- strsplit(input_2, split = " ") for (move in moves) { from = as.integer(move[4]) to = as.integer(move[6]) n = as.integer(move[2]) stacks[[to]] <- c(stacks[[to]], rev(tail(stacks[[from]], n))) stacks[[from]] <- head(stacks[[from]], -n) } lapply(stacks, tail, n = 1) |> paste(collapse = "")[1] "QNNTGTPFN" stacks <- lapply(input_1, substring, first = stack_ixs, last = stack_ixs) |> rev() |> transpose_list() |> lapply(drop_empty) # Same as before for (move in moves) { from = as.integer(move[4]) to = as.integer(move[6]) n = as.integer(move[2]) stacks[[to]] <- c(stacks[[to]], tail(stacks[[from]], n)) # Don't reverse stacks[[from]] <- head(stacks[[from]], -n) } lapply(stacks, tail, n = 1) |> paste(collapse = "")[1] "GGNPJBTTR" def find_marker(input, n_letters): for ix in range(len(input)): letters = input[ix:ix + n_letters] if len(letters) == len(set(letters)): return ix + n_letters with open('data/day6.txt') as f: input = f.readline() find_marker(input, n_letters=4)1802 find_marker(input, n_letters=14)3551 input <- readLines("data/day7.txt", warn = FALSE) dirs = list(`/` = list(".dir_size" = 0)) for (cmd in input) { if (cmd == "$ cd /") path <- '/' else if (cmd == "$ cd ..") path <- head(path, -1) else if (startsWith(cmd, "$ cd")) { dir_name <- tail(strsplit(cmd, " ")[[1]], 1) path <- c(path, dir_name) } else if (cmd == "$ ls") dirs[[path]] <- list(".dir_size" = 0) else if (!startsWith(cmd, "dir")) { # Only consider files, not directories file_size <- strsplit(cmd, " ")[[1]] |> head(1) |> as.numeric() for (ix in seq_along(path)) { # Add file size to all parent directories dir_size_path <- c(head(path, ix), ".dir_size") dirs[[dir_size_path]] <- dirs[[dir_size_path]] + file_size } } else next } str(dirs, list.len = 3) # Sanity checkList of 1 $ /:List of 5 ..$ .dir_size: num 44376732 ..$ lhrfs :List of 1 .. ..$ .dir_size: num 240152 ..$ nwh :List of 2 .. ..$ .dir_size: num 834387 .. ..$ pmdj :List of 1 .. .. ..$ .dir_size: num 514336 .. [list output truncated] dir_sizes <- unlist(dirs) sum(dir_sizes[dir_sizes < 1e5])[1] 1243729 space_left <- 7e7 - dirs[[c("/", ".dir_size")]] space_needed <- 3e7 - space_left min(dir_sizes[dir_sizes > space_needed])[1] 4443914 import numpy as np def is_visible(arr_1d): """Tests for each element in arr if it's visible from the front or back.""" return [all(arr_1d[:ix] < elem) or all(arr_1d[ix + 1:] < elem) for ix, elem in enumerate(arr_1d)] input = np.genfromtxt('data/day8.txt', delimiter=1) vis = [np.apply_along_axis(is_visible, ax, input) for ax in range(input.ndim)] np.any(vis, axis=0).sum()1854 def score_elem(arr, elem): """Computes the score (other visible trees) in one direction.""" if arr.size == 0: score = 0 # Edge tree elif all(elem > arr): score = len(arr) # Largest tree, sees all other trees in the row else: score = np.where(arr >= elem)[0][0] + 1 # Sees until next equal tree return score input = np.genfromtxt('data/day8.txt', dtype=int, delimiter=1) scores = np.zeros((4,) + input.shape, dtype=int) for row_ix, row in enumerate(input): for col_ix, elem in enumerate(row): left = np.flip(row[:col_ix]) right = row[col_ix + 1:] up = np.flip(input[:row_ix, col_ix]) down = input[row_ix + 1:, col_ix] for dir_ix, arr in enumerate([left, right, up, down]): scores[dir_ix, row_ix, col_ix] = score_elem(arr, elem) scores = np.prod(scores, axis=0) print(scores.max())527340 That’s how far I’ve got for the 2022 edition of Advent of Code. :facepalm: Wish me better luck next time!