Day 1

Part 1

``````input <- as.numeric(readLines("2020/01-input"))

sum2 <- function(input, target) {
for (i in input) {
for (j in input) {
if (i + j == target) {
return(i * j)
}
}
}
}

sum2(input, 2020)``````
``[1] 691771``
``0.01 sec elapsed``

Part 2

``````input <- as.numeric(readLines("2020/01-input"))

sum3 <- function(input, target) {
for (i in input) {
for (j in input) {
for (l in input) {
if (i + j + l == target) {
return(i * j * l)
}
}
}
}
}

sum3(input, 2020)``````
``[1] 232508760``
``0.043 sec elapsed``

Day 2

Part 1

``````library(purrr)
library(stringr)

numbers <- as.numeric(str_extract_all(x, "[0-9]+")[[1]])
chars <- str_extract_all(x, "[a-z]+")[[1]]

count <- str_count(chars[2], chars[1])
(numbers[1] <= count) & (numbers[2] >= count)
}

``[1] 439``
``0.078 sec elapsed``

Part 2

``````library(purrr)
library(stringr)

numbers <- as.numeric(str_extract_all(x, "[0-9]+")[[1]])
chars <- str_extract_all(x, "[a-z]+")[[1]]

loc1 <- str_sub(chars[2], numbers[1], numbers[1])
loc2 <- str_sub(chars[2], numbers[2], numbers[2])

sum(loc1 == chars[1], loc2 == chars[1]) == 1

}

``[1] 584``
``0.063 sec elapsed``

Day 3

Part 1

``````library(purrr)

# turn input into logical matrix
mat <- strsplit(input, "") %>%
map(~.x == "#") %>%
reduce(rbind)

traverse <- function(mat, right, down) {
x <- y <- 1

height <- nrow(mat)
width <- ncol(mat)

# Check tree collision
trees <- 0
repeat {
y <- y + down
x <- (x + right) %% width
x <- ifelse(x == 0, width, x)
trees <- trees + mat[y, x]
if (y >= height) break
}
trees
}

traverse(mat, 3, 1)``````
``````elt
214 ``````
``0.017 sec elapsed``

Part 2

``````library(purrr)

# turn input into logical matrix
mat <- strsplit(input, "") %>%
map(~.x == "#") %>%
reduce(rbind)

traverse <- function(mat, right, down) {
x <- y <- 1

height <- nrow(mat)
width <- ncol(mat)

# Check tree collision
trees <- 0
repeat {
y <- y + down
x <- (x + right) %% width
x <- ifelse(x == 0, width, x)
trees <- trees + mat[y, x]
if (y >= height) break
}
trees
}

prod(
traverse(mat, 1, 1),
traverse(mat, 3, 1),
traverse(mat, 5, 1),
traverse(mat, 7, 1),
traverse(mat, 1, 2)
)``````
``[1] 8336352024``
``0.016 sec elapsed``

Day 4

Part 1

``````library(purrr)
library(stringr)
library(magrittr)

passports <- str_split(paste(input, collapse = "\n"), "\n\n")[[1]]

matches <- c("byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid")

valid <- str_extract_all(passports, paste0(matches, collapse = "|")) %>%
map_lgl(~all(matches %in% .x))

sum(valid)``````
``[1] 182``
``0.013 sec elapsed``

Part 2

``````library(purrr)
library(stringr)
library(magrittr)

passports <- str_split(paste(input, collapse = "\n"), "\n\n")[[1]]

matches <- c("byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid")

valid <- str_extract_all(passports, paste0(matches, collapse = "|")) %>%
map_lgl(~all(matches %in% .x))

create_list <- function(x) {
x <- str_split(x, "[ \n]")[[1]]
x_split <- str_split(x, ":")

setNames(map(x_split, 2), map(x_split, 1))
}

map_dfr(create_list)

int <- as.integer

check_byr <- function(x) int(x) >= 1920 & int(x) <= 2002

check_iyr <- function(x) int(x) >= 2010 & int(x) <= 2020

check_eyr <- function(x) int(x) >= 2020 & int(x) <= 2030

check_hgt <- function(x) {
value <- as.numeric(str_extract(x, "[0-9]+"))
unit <- str_remove(x, "[0-9]+")

if_else(
unit %in% c("in", "cm"),
if_else(
unit == "in",
value >= 59 & value <= 76,
value >= 150 & value <= 193
),
FALSE
)
}

check_hcl <- function(x) {
str_detect(x, "#[0-9a-f]{6}")
}

check_ecl <- function(x) {
x %in% c("amb", "blu", "brn", "gry", "grn", "hzl", "oth")
}

check_pid <- function(x) {
str_detect(x, "^[0-9]{9}\$")
}

library(dplyr)

filter(
check_hgt(hgt),
check_byr(byr),
check_hcl(hcl),
check_ecl(ecl),
check_pid(pid),
check_iyr(iyr),
check_eyr(eyr)
) %>%
nrow()``````
``[1] 109``
``0.093 sec elapsed``

Day 5

Part 1

``````input <- readLines("2020/05-input")

input <- gsub(c("[FL]"), c("0"), input)
input <- gsub(c("[BR]"), c("1"), input)

id <- strtoi(input, base = 2)

max(id)``````
``[1] 888``
``0.006 sec elapsed``

Part 2

``````input <- readLines("2020/05-input")

input <- gsub(c("[FL]"), c("0"), input)
input <- gsub(c("[BR]"), c("1"), input)

id <- strtoi(input, base = 2)

setdiff(seq(min(id), max(id)), id)``````
``[1] 522``
``0.007 sec elapsed``

Day 6

Part 1

``````library(tidyverse)
library(tidytext)

tibble(input = .) %>%
unnest_paragraphs(text, input) %>%
rowid_to_column("group_id") %>%
unnest_tokens(text, text) %>%
rowid_to_column("person_id") %>%
unnest_characters(text, text)

count(group_id, text) %>%
nrow()``````
``[1] 6542``
``1.752 sec elapsed``

Part 2

``````library(tidyverse)
library(tidytext)

tibble(input = .) %>%
unnest_paragraphs(text, input) %>%
rowid_to_column("group_id") %>%
unnest_tokens(text, text) %>%
rowid_to_column("person_id") %>%
unnest_characters(text, text)

group_by(group_id) %>%
mutate(group_size = n_distinct(person_id)) %>%
count(group_size, text) %>%
filter(group_size == n) %>%
nrow()``````
``[1] 3299``
``0.103 sec elapsed``

Day 7

Part 1

``````library(stringr)

containing_bag <- function(x) {
str_extract(str_subset(input, paste0(".+", x)), "^.+?bag")
}

used_bags <- c()

new_bags <- "shiny gold bag"

repeat {

used_bags <- c(used_bags, new_bags)
break
}

used_bags <- c(used_bags, new_bags)

}

length(setdiff(used_bags, "shiny gold bag"))``````
``[1] 238``
``5.546 sec elapsed``

Part 2

``````library(stringr)

bags <- str_extract_all(input, "(?<=[0-9] ).*?bag")
number <- str_extract_all(input, "[0-9]+")
number <- lapply(number, as.integer)
names(number) <- names(bags) <- str_extract(input, "^.+?bag")

find_size <- function(x, n) {
contains <- bags[[x]]
if (length(contains) == 0) return(n)
n_bags <- map2_int(contains, number[[x]], find_size)
sum(c(n_bags, 1L) * n)
}

find_size(x = "shiny gold bag", n = 1) - 1``````
``[1] 82930``
``0.016 sec elapsed``

Day 8

Part 1

``````input <- readLines("2020/08-input")

run <- function(input, part2 = FALSE) {
len <- length(input)
n_times <- integer(len)

accumulator <- 0

i <- 1

repeat {
x <- strsplit(input[i], " ")[[1]]

n_times[i] <- n_times[i] + 1

if (i > len) {
return(accumulator)
}
if (n_times[i] == 2) {
if (part2) {
return(NA)
} else {
return(accumulator)
}
}

if (x[1] == "nop") {
i <- i + 1
} else if (x[1] == "acc") {
i <- i + 1
} else if (x[1] == "jmp") {
}
}
}

run(input)``````
``[1] 1654``
``0.224 sec elapsed``

Part 2

``````library(stringr)

run <- function(input, part2 = FALSE) {
len <- length(input)
n_times <- integer(len)

accumulator <- 0

i <- 1

repeat {
x <- strsplit(input[i], " ")[[1]]

n_times[i] <- n_times[i] + 1

if (i > len) {
return(accumulator)
}
if (n_times[i] == 2) {
if (part2) {
return(NA)
} else {
return(accumulator)
}
}

if (x[1] == "nop") {
i <- i + 1
} else if (x[1] == "acc") {
i <- i + 1
} else if (x[1] == "jmp") {
}
}
}

for (i in seq_along(input)) {
input0 <- input
if (str_detect(input0[i], "acc")) next

if (str_detect(input0[i], "nop")) {
input0[i] <- str_replace(input0[i], "nop", "jmp")
} else {
input0[i] <- str_replace(input0[i], "jmp", "nop")
}

res <- run(input0, part2 = TRUE)
if(!is.na(res)) break
}
res``````
``[1] 833``
``17.011 sec elapsed``

Day 9

Part 1

``````input <- as.numeric(readLines("2020/09-input"))

i <- 1

repeat {
sums <- colSums(combn(input[seq(i, i + 24)], 2))
if(!any(input[i + 25] == sums)) break
i <- i + 1
}

input[i + 25]``````
``[1] 1930745883``
``0.162 sec elapsed``

Part 2

``````input <- as.numeric(readLines("2020/09-input"))

i <- 1

repeat {
sums <- colSums(combn(input[seq(i, i + 24)], 2))
if(!any(input[i + 25] == sums)) break
i <- i + 1
}

target <- input[i + 25]

i <- 1
step <- 1

repeat {
res <- sum(input[seq(i, i + step)])

if (res == target) break

if (res > target) {
i <- i + 1
step <- 1
next
}
step <- step + 1
}

sum(range(input[seq(i, i + step)]))``````
``[1] 268878261``
``1.353 sec elapsed``

Day 10

Part 1

``````input <- as.integer(readLines("2020/10-input"))

res <- table(diff(sort(input)))

prod(res + 1)``````
``[1] 1984``
``0.002 sec elapsed``

Part 2

``````input <- sort(as.integer(readLines("2020/10-input")))

runs <- rle(c(diff(c(0, input))))
weights <- c(1, 2, 4, 7)

options(scipen = 999)
prod(weights[runs\$lengths[runs\$values == 1]])``````
``[1] 3543369523456``
``0.002 sec elapsed``

Day 11

Part 1

``````input <- readLines("2020/11-input")

# turn input into logical matrix
mat <- strsplit(input, "") %>%
reduce(rbind)

replace <- mat

repeat {
for (i in seq_len(nrow(mat))) {
for (j in seq_len(ncol(mat))) {
if (mat[i, j] == ".") next

temp_mat <- mat
temp_mat[i, j] <- ""

conv <- temp_mat[seq(max(i-1, 1), min(i+1, nrow(mat))),
seq(max(j-1, 1), min(j+1, ncol(mat)))]

if (mat[i, j] == "L") {
if (all(conv != "#")) {
replace[i, j] <- "#"
}
}

if (mat[i, j] == "#") {
if (sum(conv == "#") >= 4) {
replace[i, j] <- "L"
}
}
}
}

if (identical(mat, replace)) break
mat <- replace
}

sum(mat == "#")``````
``[1] 2113``
``35.157 sec elapsed``

Part 2

``````input <- readLines("2020/11-input")

# turn input into logical matrix
mat <- strsplit(input, "") %>%
reduce(rbind)

find_neighbor <- function(mat, i, j, x, y) {
res <- "."
i <- i + y
j <- j + x
while (i > 0 & j > 0 & j <= ncol(mat) & i <= nrow(mat)) {
value <- mat[i,j]
if (value != ".") {
res <- value
break
}
i <- i + y
j <- j + x
}
res
}

find_all_neighbors <- function(mat, i, j) {

up <-   find_neighbor(mat, i, j, 0, -1)
down <- find_neighbor(mat, i, j, 0, 1)
right <- find_neighbor(mat, i, j, -1, 0)
left <-  find_neighbor(mat, i, j, 1, 0)

upright <- find_neighbor(mat, i, j, 1, -1)
upleft <- find_neighbor(mat, i, j, -1, -1)
downright <- find_neighbor(mat, i, j, 1, 1)
downleft <- find_neighbor(mat, i, j, -1, 1)

c(up, down, right, left, upright, upleft, downright, downleft)
}

replace <- mat

repeat {
for (i in seq_len(nrow(mat))) {
for (j in seq_len(ncol(mat))) {
if (mat[i, j] == ".") next

conv <- find_all_neighbors(mat, i, j)

if (mat[i, j] == "L") {
if (all(conv != "#")) {
replace[i, j] <- "#"
}
}

if (mat[i, j] == "#") {
if (sum(conv == "#") >= 5) {
replace[i, j] <- "L"
}
}
}
}

if (identical(mat, replace)) break

mat <- replace
}

sum(mat == "#")``````
``[1] 1865``
``18.343 sec elapsed``

Day 12

Part 1

``````input <- readLines("2020/12-input")

ship <- c(0, 0)
direction <- c(1, 0)

rotate <- function(x, phi) {
c(x[1] * cos(phi * pi / 180) - x[2] * sin(phi * pi / 180),
x[1] * sin(phi * pi / 180) + x[2] * cos(phi * pi / 180))
}

for (i in input) {
value <- as.numeric(str_extract(i, "[0-9]+"))
switch(
substr(i, 1, 1),
N = {ship[2] <- ship[2] + value},
S = {ship[2] <- ship[2] - value},
E = {ship[1] <- ship[1] + value},
W = {ship[1] <- ship[1] - value},
L = {direction <- rotate(direction, value)},
R = { direction <- rotate(direction, -value)},
F = {ship <- ship + direction * value}
)
}

sum(abs(ship))``````
``[1] 1496``
``0.033 sec elapsed``

Part 2

``````input <- readLines("2020/12-input")

ship <- c(0, 0)

waypoint <- c(10, 1)

rotate <- function(x, phi) {
c(x[1] * cos(phi * pi / 180) - x[2] * sin(phi * pi / 180),
x[1] * sin(phi * pi / 180) + x[2] * cos(phi * pi / 180))
}

for (i in input) {
value <- as.numeric(str_extract(i, "[0-9]+"))

switch(
substr(i, 1, 1),
N = {waypoint[2] <- waypoint[2] + value},
S = {waypoint[2] <- waypoint[2] - value},
E = {waypoint[1] <- waypoint[1] + value},
W = {waypoint[1] <- waypoint[1] - value},
L = {waypoint <- rotate(waypoint, value)},
R = {waypoint <- rotate(waypoint, -value)},
F = {ship <- ship + waypoint * value}
)
}

sum(abs(ship))``````
``[1] 63843``
``0.024 sec elapsed``

Day 13

Part 1

``````input <- readLines("2020/13-input")

target <- as.integer(input[1])
ids <- as.integer(str_extract_all(input[2], "[0-9]+")[[1]])

time_past <- ceiling(target / ids) * ids
which_min <- min(time_past) == time_past

(time_past[which_min] - target) * ids[which_min]``````
``[1] 2845``
``0.002 sec elapsed``

Part 2

``````input <- readLines("2020/13-input")

ids <- as.numeric(str_split(input[2], ",")[[1]])
offset <- seq_along(ids) - 1
offset <- offset[!is.na(ids)]
ids <- ids[!is.na(ids)]

timestamp <- 1
step <- 1

for (i in seq_along(ids)) {
repeat {
if ((timestamp + offset[i]) %% ids[i] == 0) break
timestamp <- timestamp + step
}

step <- prod(ids[seq_len(i)])
}

options(scipen = 999)
timestamp``````
``[1] 487905974205117``
``0.007 sec elapsed``

Day 14

Part 1

``````library(stringr)

intTo36 <- function(x) {
as.character(c(rep(0, 4), rev(as.integer(intToBits(x)))))
}

`[<-.memory` <- function(x, i, value) {
res <- intTo36(value)
x[[i]] <- res
x
}

mem <- list()
attr(mem, "class") <- "memory"

for (line in input) {
next
}
eval(parse(text = line))
}

options(scipen = 999)
sum(map_dbl(mem, ~ sum(as.numeric(.x) * (2 ^ seq(35, 0)))))``````
``[1] 15514035145260``
``0.831 sec elapsed``

Day 15

Part 1

``````input <- c(16,1,0,18,12,14,19)

res <- rep(-1, 2020)
res[seq_along(input)] <- input
for (i in 8:2020) {
if (sum(res == res[i- 1]) == 1) {
res[i] <- 0
} else {
last_calls <- which(res == res[i- 1])
res[i] <- last_calls[length(last_calls)] - last_calls[length(last_calls) - 1]
}
}
rev(res)[1]``````
``[1] 929``
``0.056 sec elapsed``

Day 16

Part 1

``````library(tidyverse)
breaks <- which(input == "")

valid_values <- input[seq(1, min(breaks) - 1)] %>%
str_extract_all("[0-9]+") %>%
map(as.numeric) %>%
map(~ c(seq(.x[1], .x[2]), seq(.x[3], .x[4])))

skip = which(input == "nearby tickets:"))

all_valid_values <- unlist(valid_values)

check_value <- function(x, ref) {
map_dbl(x, ~ ifelse(.x %in% ref, NA, .x))
}

wrong <- apply(tickets, 2, check_value, all_valid_values)

sum(wrong, na.rm = TRUE)``````
``[1] 20060``
``0.359 sec elapsed``

Part 2

``````library(tidyverse)
breaks <- which(input == "")

valid_values <- input[seq(1, min(breaks) - 1)] %>%
str_extract_all("[0-9]+") %>%
map(as.numeric) %>%
map(~ c(seq(.x[1], .x[2]), seq(.x[3], .x[4])))

skip = which(input == "nearby tickets:"))

all_valid_values <- unlist(valid_values)

check_value <- function(x, ref) {
map_dbl(x, ~ ifelse(.x %in% ref, NA, .x))
}

wrong <- apply(tickets, 2, check_value, all_valid_values)

valid_ticket <- tickets[rowSums(!is.na(wrong)) == 0, ]

can_be <- function(x) {
which(map_lgl(valid_values, ~all(x %in% .x)))
}

pos <- numeric(length(valid_values))

candidates <- map(valid_ticket, can_be)

repeat {
variable_ind <- which(lengths(candidates) == 1)
if(length(variable_ind) == 0) break

ref_ind <- candidates[[variable_ind]]

pos[variable_ind] <- ref_ind

candidates <- map(candidates, setdiff, ref_ind)
}

my_ticket <- as.numeric(str_split(input[min(breaks) + 2], ",")[[1]])

fields <- input[seq(1, min(breaks) - 1)] %>%
str_detect("^departure")

options(scipen = 999)
prod(my_ticket[fields[pos]])``````
``[1] 2843534243843``
``0.249 sec elapsed``

Day 17

Part 1

``````library(dplyr)
library(tidyr)

start <- tibble(
x = rep(seq(7, 14), 8),
y = rev(rep(seq(7, 14), each = 8)),
z = 10,
state = strsplit(input, "") %>% unlist()
)

space <- expand_grid(x = seq(1, 20), y = seq(1, 20), z = seq(1, 20)) %>%
left_join(start, by = c("x", "y", "z")) %>%
mutate(state = if_else(is.na(state), ".", state)) %>%
mutate(row = row_number())

find_neighbors <- function(dat) {
space %>%
filter(abs(x - dat\$x) <= 1, abs(y - dat\$y) <= 1, abs(z - dat\$z) <= 1,
!(x == dat\$x & y == dat\$y & z == dat\$z)) %>%
pull(row)
}

all_neighbors <- map(seq_len(nrow(space)), ~find_neighbors(space[.x, ]))

next_state <- function(x, nbs) {
if (x == "#") {
if (sum(nbs == "#") %in% c(2, 3)) {
return("#")
} else {
return(".")
}
} else {
if (sum(nbs == "#") == 3) {
return("#")
} else {
return(".")
}
}
}

for(iter in 1:6) {
all_neighbors_states <- map(all_neighbors, ~ space\$state[.x])
space\$state <- map2_chr(space\$state, all_neighbors_states, next_state)
}

sum(space\$state == "#")``````
``[1] 280``
``18.453 sec elapsed``

Part 2

``````library(dplyr)
library(tidyr)

start <- tibble(
x = rep(seq(7, 14), 8),
y = rev(rep(seq(7, 14), each = 8)),
z = 0,
w = 0,
state = strsplit(input, "") %>% unlist()
)

space <- expand_grid(x = seq(1, 20),
y = seq(1, 20),
z = seq(-6, 6),
w = seq(-6, 6)) %>%
left_join(start, by = c("x", "y", "z", "w")) %>%
mutate(state = if_else(is.na(state), ".", state)) %>%
mutate(row = row_number())

find_neighbors <- function(dat) {
space %>%
filter(abs(x - dat\$x) <= 1,
abs(y - dat\$y) <= 1,
abs(z - dat\$z) <= 1,
abs(w - dat\$w) <= 1,
!(x == dat\$x & y == dat\$y & z == dat\$z & w == dat\$w)) %>%
pull(row)
}

all_neighbors <- map(seq_len(nrow(space)), ~find_neighbors(space[.x, ]))

next_state <- function(x, nbs) {
if (x == "#") {
if (sum(nbs == "#") %in% c(2, 3)) {
return("#")
} else {
return(".")
}
} else {
if (sum(nbs == "#") == 3) {
return("#")
} else {
return(".")
}
}
}

for(iter in 1:6) {
all_neighbors_states <- map(all_neighbors, ~ space\$state[.x])
space\$state <- map2_chr(space\$state, all_neighbors_states, next_state)
}

sum(space\$state == "#")``````
``[1] 1696``
``442.808 sec elapsed``

Day 18

Part 1

``````library(stringr)
library(purrr)

`%+%` <- function(a, b) a + b
`%*%` <- function(a, b) a * b

eval_string <- function(x) {
map_dbl(x, ~eval(parse(text = .x)))
}

options(scipen = 999)
input %>%
str_replace_all(c("\\+" = "%\\+%", "\\*" = "%\\*%")) %>%
eval_string() %>%
sum()``````
``[1] 8298263963837``
``0.014 sec elapsed``

Part 2

``````library(stringr)
library(purrr)

eval_string_rev <- function(x) {
rev_env <- new.env()
rev_env\$`+` <- function(a, b) base::`*`(a, b)
rev_env\$`*` <- function(a, b) base::`+`(a, b)
map_dbl(x, ~eval(parse(text = .x), envir = rev_env))
}

options(scipen = 999)
input %>%
str_replace_all(c("\\+" = "temp", "\\*" = "+", "temp" = "*")) %>%
eval_string_rev() %>%
sum()``````
``[1] 145575710203332``
``0.01 sec elapsed``

Day 19

Part 1

``````library(stringr)
library(purrr)
break_point <- which(input == "")

rules_raw <- input[seq(1, break_point - 1)]
rules_raw <- str_remove_all(rules_raw, "\"")
rules_raw <- str_split(rules_raw, ": ")
rules <- map_chr(rules_raw, 2)
rules <- map_chr(str_split(rules, " "), ~paste(glue::glue("_{.x}_"),collapse = ""))
rules <- str_replace_all(rules, c("_\\|_" = "\\|", "_a_" = "a", "_b_" = "b"))
rules <- paste0("(", rules, ")")
names(rules) <- paste0("_", map(rules_raw, 1), "_")

messages <- input[seq(break_point + 1, length(input))]

master <- "_0_"
while(str_detect(master, "[0-9]")) {
master <- str_replace_all(master, rules)
}

sum(str_detect(messages, glue::glue("^{master}\$")))``````
``[1] 162``
``0.115 sec elapsed``

Part 2

``````library(stringr)
library(purrr)
break_point <- which(input == "")

rules_raw <- input[seq(1, break_point - 1)]
rules_raw <- str_remove_all(rules_raw, "\"")
rules_raw <- str_split(rules_raw, ": ")
rules <- map_chr(rules_raw, 2)
rules <- map_chr(str_split(rules, " "), ~paste(glue::glue("_{.x}_"),collapse = ""))
rules <- str_replace_all(rules, c("_\\|_" = "\\|", "_a_" = "a", "_b_" = "b"))
rules <- paste0("(", rules, ")")
names(rules) <- paste0("_", map(rules_raw, 1), "_")
rules["_8_"] <- "(_42_+)"
rules["_11_"] <- "(_42__31_|_42__42__31__31_|_42__42__42__31__31__31_|_42__42__42__42__31__31__31__31_|_42__42__42__42__42__31__31__31__31__31_|_42__42__42__42__42__42__42__31__31__31__31__31__31__31_)"

messages <- input[seq(break_point + 1, length(input))]

master <- "_0_"
while(str_detect(master, "[0-9]")) {
master <- str_replace_all(master, rules)
}

sum(grepl(glue::glue("^{master}\$"), messages))``````
``[1] 267``
``0.282 sec elapsed``

Day 20

Part 1

``````library(tidyverse)

input <- str_remove(input, "\n\$")

tiles <- str_split(input, "\n\n")[[1]]

tile_info <- function(x) {
lines <- str_split(x, "\n")[[1]]

id <- str_extract(lines[1], "[0-9]+")
grid <- lines[-1]

sides <- c(
paste0(str_sub(grid, 1, 1), collapse = ""),
paste0(str_sub(grid, length(grid), length(grid)), collapse = ""),
grid[c(1, length(grid))]
)

tibble(id, side = c(sides, stringi::stri_reverse(sides)))
}

tile_sides <- map_dfr(tiles, tile_info)

options(scipen = 999)
joints <- inner_join(tile_sides, tile_sides, by = "side") %>%
filter(id.x != id.y) %>%
transmute(pair = map2_chr(id.x, id.y, ~
paste(sort(c(.x, .y)), collapse = " ")
)) %>%
distinct() %>%
separate(pair, c("a", "b"), " ")

joints %>%
pivot_longer(everything()) %>%
count(value) %>%
filter(n == 2) %>%
summarize(res = prod(as.numeric(value))) %>%
pull(res)``````
``[1] 18482479935793``
``0.227 sec elapsed``

Part 2

``````library(tidyverse)

input <- str_remove(input, "\n\$")

tiles <- str_split(input, "\n\n")[[1]]

tile_info <- function(x) {
lines <- str_split(x, "\n")[[1]]

id <- str_extract(lines[1], "[0-9]+")
grid <- lines[-1]

sides <- c(
paste0(str_sub(grid, 1, 1), collapse = ""),
paste0(str_sub(grid, length(grid), length(grid)), collapse = ""),
grid[c(1, length(grid))]
)

tibble(id, side = c(sides, stringi::stri_reverse(sides)))
}

tile_sides <- map_dfr(tiles, tile_info)

options(scipen = 999)
joints <- inner_join(tile_sides, tile_sides, by = "side") %>%
filter(id.x != id.y) %>%
transmute(pair = map2_chr(id.x, id.y, ~
paste(sort(c(.x, .y)), collapse = " ")
)) %>%
distinct() %>%
separate(pair, c("a", "b"), " ")

current <- joints %>%
pivot_longer(everything()) %>%
count(value) %>%
filter(n == 2) %>%
slice(1) %>%
pull(value)

middle <- joints %>%
pivot_longer(everything()) %>%
count(value) %>%
filter(n == 4) %>%
pull(value)

non_middle <- joints %>%
filter(!a %in% middle, !b %in% middle)

places <- matrix(NA, 12, 12)

used <- c()
round <- c()

repeat {
round <- c(round, current)

next_tile <- non_middle %>%
filter(a %in% current | b %in% current, !a %in% used, !b %in% used) %>%
slice(1) %>%
unlist() %>%
setdiff(current)

if(length(next_tile) == 0) break
used <- c(used, current)
current <- next_tile
}

places[1, 1:12] <- round[1:12]
places[2:12, 12] <- round[13:23]
places[12, 11:1] <- round[24:34]
places[11:2, 1] <- round[35:44]

for (i in 2:11) {
for (j in 2:11) {
partners <- c(places[i-1, j], places[i, j-1])

places[i, j] <- intersect(
joints %>%
filter(a %in% partners[1] | b %in% partners[1]) %>%
unlist() %>%
setdiff(partners[1]),
joints %>%
filter(a %in% partners[2] | b %in% partners[2]) %>%
unlist() %>%
setdiff(partners[1])
) %>%
setdiff(places[i - 1, j - 1])
}
}

extract_full_grid <- function(x) {
str_split(x, "\n")[[1]][-1] %>%
str_split("") %>%
unlist() %>%
matrix(nrow = 10, byrow = TRUE)
}

full_tiles <- map(tiles, extract_full_grid)
names(full_tiles) <- str_extract(tiles, "[0-9]+")

rotate <- function(x) t(apply(x, 2, rev))

all_tiles <- map(1:12, ~map(1:12, ~list()))

all_tiles[[1]][[1]] <- full_tiles[[places[1, 1]]][, 10:1]

all_symmmetries <- list(
function(x) x,
function(x) rotate(x),
function(x) rotate(rotate(x)),
function(x) rotate(rotate(rotate(x))),
function(x) x[, 10:1],
function(x) rotate(x[, 10:1]),
function(x) rotate(rotate(x[, 10:1])),
function(x) rotate(rotate(rotate(x[, 10:1])))
)

for (i in 2:12) {
tile <- full_tiles[[places[1, i]]]

tile_symmetries <- map(all_symmmetries, ~.x(tile))

tile_which <- map_lgl(tile_symmetries, ~ all(all_tiles[[1]][[i - 1]][, 10] == .x[, 1]))

all_tiles[[1]][[i]] <- tile_symmetries[[which(tile_which)]]
}

for (j in 2:12) {
for (i in 1:12) {
tile <- full_tiles[[places[j, i]]]

tile_symmetries <- map(all_symmmetries, ~.x(tile))

tile_which <- map_lgl(tile_symmetries, ~ all(all_tiles[[j - 1]][[i]][10, ] == .x[1, ]))

all_tiles[[j]][[i]] <- tile_symmetries[[which(tile_which)]]
}
}

x <- all_tiles[[1]][[1]]

get_inner <- function(x) {
x[2:9, 2:9]
}

lake <- reduce(map(all_tiles, ~reduce(map(.x, get_inner), cbind)), rbind)

monster <- c(
"                  # ",
"#    ##    ##    ###",
" #  #  #  #  #  #   "
) %>%
str_split("") %>%
unlist() %>%
matrix(nrow = 3, byrow = TRUE)

for (turn in 1:8) {
for (i in 1:94) {
for (j in 1:77) {
inlake <- lake[seq(i, i + 2), seq(j, j + 19)][monster == "#"]

if (all(inlake %in% c("#", "0"))) {
lake[seq(i, i + 2), seq(j, j + 19)][monster == "#"] <- "0"
}
}
}
lake <- rotate(lake)
if(turn == 4) {
lake <- lake[, seq_len(nrow(lake))]
}
}

sum(lake == "#")``````
``[1] 2118``
``1.719 sec elapsed``

Day 21

Part 1

``````library(stringr)
library(purrr)

allergies <- str_extract(input, "\\(.*")
allergies <- str_remove(allergies, "\\(contains ")
allergies <- str_remove(allergies, "\\)")
allergies <- str_split(allergies, ", ")

ingredient <- str_extract(input, "[ a-z]+")
ingredient <- str_extract_all(ingredient, "[a-z]+")

all_allergies <- unique(unlist(allergies))
all_ingredient <- character(length(all_allergies))

repeat {
res <- length(unlist(ingredient))

for (i in seq_along(all_allergies)) {
x <- all_allergies[i]

x_foods <- ingredient[map_lgl(allergies, ~any(.x %in% x))]

candidates <- reduce(x_foods, intersect)
if (length(candidates) != 1) next
all_ingredient[i] <- candidates
ingredient <- map(ingredient, setdiff, all_ingredient)
}

new_res <- length(unlist(ingredient))

if (res == new_res) break
res <- new_res
}

length(unlist(ingredient))``````
``[1] 2724``
``0.04 sec elapsed``

Part 2

``````library(stringr)
library(purrr)

allergies <- str_extract(input, "\\(.*")
allergies <- str_remove(allergies, "\\(contains ")
allergies <- str_remove(allergies, "\\)")
allergies <- str_split(allergies, ", ")

ingredient <- str_extract(input, "[ a-z]+")
ingredient <- str_extract_all(ingredient, "[a-z]+")

all_allergies <- unique(unlist(allergies))
all_ingredient <- character(length(all_allergies))

repeat {
res <- length(unlist(ingredient))

for (i in seq_along(all_allergies)) {
x <- all_allergies[i]

x_foods <- ingredient[map_lgl(allergies, ~any(.x %in% x))]

candidates <- reduce(x_foods, intersect)
if (length(candidates) != 1) next
all_ingredient[i] <- candidates
ingredient <- map(ingredient, setdiff, all_ingredient)
}

new_res <- length(unlist(ingredient))

if (res == new_res) break
res <- new_res
}

paste(all_ingredient[order(all_allergies)], collapse = ",")``````
``[1] "xlxknk,cskbmx,cjdmk,bmhn,jrmr,tzxcmr,fmgxh,fxzh"``
``0.028 sec elapsed``

Day 22

Part 1

``````input <- readLines("2020/22-input")

bp <- which(input == "")

player1 <- as.numeric(input[seq(2, bp-1)])
player2 <- as.numeric(input[seq(bp + 2, length(input))])

repeat {
if (player1[1] > player2[1]) {
player1 <- c(player1[-1], player1[1], player2[1])
player2 <- player2[-1]
} else {
player2 <- c(player2[-1], player2[1], player1[1])
player1 <- player1[-1]
}
if (length(player1) == 0 | length(player2) == 0) break
}

sum(player1 * rev(seq_along(player1))) +
sum(player2 * rev(seq_along(player2)))``````
``[1] 32472``
``0.011 sec elapsed``

Part 2

``````library(purrr)

bp <- which(input == "")

player1 <- as.numeric(input[seq(2, bp - 1)])
player2 <- as.numeric(input[seq(bp + 2, length(input))])

play_game <- function(hand1, hand2, subgame = FALSE) {
previous_hands1 <- list()
previous_hands2 <- list()
repeat {
if (any(map_lgl(previous_hands1, ~identical(.x, hand1))) &
any(map_lgl(previous_hands2, ~identical(.x, hand2)))) {
if (subgame) {
return(TRUE)
} else {
return(sum(hand1 * rev(seq_along(hand1))) +
sum(hand2 * rev(seq_along(hand2))))
}
}

draw1 <- hand1[1]
draw2 <- hand2[1]

optim <- (max(hand1) > max(hand2)) &
max(hand1) > (length(c(hand1, hand2))) &
subgame
if(optim) {
return(TRUE)
}

if (draw1 < length(hand1) & draw2 < length(hand2)) {
winner <- play_game(hand1[seq_len(draw1) + 1],
hand2[seq_len(draw2) + 1], subgame = TRUE)
} else {
winner <- hand1[1] > hand2[1]
}

previous_hands1 <- c(previous_hands1, list(hand1))
previous_hands2 <- c(previous_hands2, list(hand2))

if (winner) {
hand1 <- c(hand1[-1], hand1[1], hand2[1])
hand2 <- hand2[-1]
} else {
hand2 <- c(hand2[-1], hand2[1], hand1[1])
hand1 <- hand1[-1]
}
if (length(hand1) == 0 | length(hand2) == 0) break
}

if (subgame) {
return(length(hand2) == 0)
} else {
return(sum(hand1 * rev(seq_along(hand1))) +
sum(hand2 * rev(seq_along(hand2))))
}
}

play_game(player1, player2)``````
``[1] 36463``
``17.005 sec elapsed``

Day 23

Part 1

``````input <- c(4, 7, 6, 1, 3, 8, 2, 5, 9)
current <- input[1]

a <- numeric(length(input))

input_len <- length(input)

for (i in seq_along(a)) {
which_i <- which(input == i)
if (which_i == input_len) {
a[i] <- input[1]
} else {
a[i] <- input[which_i + 1]
}
}

for (i in 1:100) {

pick1 <- a[current]
pick2 <- a[pick1]
pick3 <- a[pick2]
pick4 <- a[pick3]

a[current] <- pick4

dest <- current - 1

if (dest == 0) {
dest <- input_len
}

while (dest %in% c(pick1, pick2, pick3)) {
dest <- dest - 1
}

if (dest == 0) {
dest <- input_len
}

while (dest %in% c(pick1, pick2, pick3)) {
dest <- dest - 1
}

end <- a[dest]

a[pick3] <- end
a[dest] <- pick1

current <- a[current]
}

res <- numeric(length(a))
res[1] <- 1

for (i in 2:length(a)) {
res[i] <- a[res[i-1]]
}

paste0(res[-1], collapse = "")``````
``[1] "97245386"``
``0.029 sec elapsed``

Part 2

``````input <- c(4, 7, 6, 1, 3, 8, 2, 5, 9)
current <- input[1]

a <- numeric(length(input))

input_len <- length(input)

a <- c(3, 5, 8, 7, 9, 1, 6, 2, 10,  seq(11, 1000000), 4)

tictoc::tic()
for (i in 1:10000000) {

pick1 <- a[current]
pick2 <- a[pick1]
pick3 <- a[pick2]
pick4 <- a[pick3]

a[current] <- pick4

dest <- current - 1

if (dest == 0) {
dest <- input_len
}

while (dest %in% c(pick1, pick2, pick3)) {
dest <- dest - 1
}

if (dest == 0) {
dest <- input_len
}

while (dest %in% c(pick1, pick2, pick3)) {
dest <- dest - 1
}

end <- a[dest]

a[pick3] <- end
a[dest] <- pick1

current <- a[current]
}
tictoc::toc()

a[1] * a[a[1]]``````
``25.478 sec elapsed``
``[1] 43717931544``
``25.49 sec elapsed``

Day 24

Part 1

``````library(stringr)
library(purrr)

moves <- c(
e = 1 + 0i,
se = 0 - 1i,
sw = -1 - 1i,
w = -1 + 0i,
nw = 0 + 1i,
ne = 1 + 1i
)
flips <- input %>%
str_extract_all("[ns]?[ew]") %>%
map(~moves[.x]) %>%
map(sum) %>%
reduce(c)

flips %>%
table() %>%
{sum(. %% 2 == 1)}``````
``[1] 386``
``0.013 sec elapsed``

Part 2

``````library(stringr)
library(purrr)

moves <- c(
e = 1 + 0i,
se = 0 - 1i,
sw = -1 - 1i,
w = -1 + 0i,
nw = 0 + 1i,
ne = 1 + 1i
)
flips <- input %>%
str_extract_all("[ns]?[ew]") %>%
map(~moves[.x]) %>%
map(sum) %>%
reduce(c)

n_neighbors <- function(x, y, moves) {
rowSums(matrix(outer(x, moves, `+`) %in% y, ncol = length(moves)))
}
black <- as.complex(names(table(flips)[table(flips) %% 2 == 1]))

for (i in 1:100) {
stay_black <- n_neighbors(black, black, moves) == 1

white_candidates <- map(black, ~.x + moves) %>%
unlist() %>%
unique()

new_black_ind <- n_neighbors(white_candidates, black, moves) == 2

new_black <- white_candidates[new_black_ind]

black <- c(black[stay_black], new_black)
}

length(black)``````
``[1] 4214``
``1.635 sec elapsed``

Day 25

Part 1

``````div <- 20201227

card_public <- 10943862
door_public <- 12721030

transform <- function(subject, lpt) {
value <- 1
c <- 0
while (c < lpt) {
value <- value * subject
value <- value %% div
c <- c + 1
}
value
}

bruteforce <- function(value_goal) {
lpt <- 1
value <- 1
repeat {
value <- value * 7
value <- value %% div
if (value == value_goal) {
return(lpt)
}
lpt <- lpt + 1
}
}

card_lpt_size <- bruteforce(card_public)
door_lpt_size <- bruteforce(door_public)

transform(door_public, card_lpt_size)``````
``[1] 5025281``
``8.838 sec elapsed``