My 2016 Solutions

Day 1

Part 1

library(stringr)
input <- readLines("2016/01-input")

instructions <- strsplit(input, ", ")[[1]]

directions <- str_extract(instructions, ".{1}")
value <- as.numeric(str_extract(instructions, "[0-9]+"))

position <- c(0, 0)
arrow <- c(0, 1)

for (i in seq_along(directions)) {
  if (directions[i] == "R") {
    arrow <- rev(arrow) * c(1, -1)
  } else if (directions[i] == "L") {
    arrow <- rev(arrow * c(1, -1))
  }
  position <- position + arrow * value[i]
}
sum(abs(position))
[1] 230
0.02 sec elapsed

Part 2

library(stringr)
input <- readLines("2016/01-input")

instructions <- strsplit(input, ", ")[[1]]

directions <- str_extract(instructions, ".{1}")
value <- as.numeric(str_extract(instructions, "[0-9]+"))

position <- matrix(0, nrow = 1, ncol = 2)
arrow <- matrix(c(0, 1), nrow = 1, ncol = 2)

last <- function(x) x[nrow(x), ]

for (i in seq_along(directions)) {
  if (directions[i] == "R") {
    arrow <- rev(arrow) * c(1, -1)
  } else if (directions[i] == "L") {
    arrow <- rev(arrow * c(1, -1))
  }

  for (step in seq_len(value[i])) {
    position <- rbind(position, arrow + last(position))
  }
}

sum(abs(position[which(duplicated(position))[1], ]))
[1] 154
0.037 sec elapsed

Day 2

Part 1

input <- readLines("2016/02-input")

directions <- strsplit(input, "")

pad <- matrix(c(1, 4, 7, 2, 5, 8, 3, 6, 9), nrow = 3)

move <- list(U = c(-1, 0), D = c(1, 0), L = c(0, -1), R = c(0, 1))

pos <- c(2, 2)

password <- numeric()

for (i in directions) {
  for (j in i) {
    pos <- pmax(pmin(pos + move[[j]], 3), 1)
  }
  password <- c(password, pad[pos[1], pos[2]])
}

paste(password, collapse = "")
[1] "47978"
0.048 sec elapsed

Part 2

input <- readLines("2016/02-input")

directions <- strsplit(input, "")

pad <- matrix(c(NA, NA, 5, NA, NA,
                NA, 2, 6, "A", NA,
                1, 3, 7, "B", "D",
                NA, 4, 8, "C", NA,
                NA, NA, 9, NA, NA), nrow = 5)

move <- list(U = c(-1, 0), D = c(1, 0), L = c(0, -1), R = c(0, 1))

pos <- c(3, 1)

password <- numeric()

for (i in directions) {
  for (j in i) {

    my_move <- move[[j]]
    if (j == "U" & pad[pos[1], pos[2]] %in% c("5", "2", "1", "4", "9") ||
        j == "D" & pad[pos[1], pos[2]] %in% c("5", "A", "D", "C", "9") ||
        j == "L" & pad[pos[1], pos[2]] %in% c("1", "2", "5", "A", "D") ||
        j == "R" & pad[pos[1], pos[2]] %in% c("1", "4", "9", "C", "D")) {
      my_move <- c(0, 0)
    }

    pos <- pos + my_move
  }
  password <- c(password, pad[pos[1], pos[2]])
}

paste(password, collapse = "")
[1] "659AD"
0.062 sec elapsed

Day 3

Part 1

input <- readLines("2016/03-input")

valid_triangle <- function(x) {
  numbers <- stringr::str_extract_all(x, pattern = "[0-9]+")[[1]]
  numbers <- sort(as.numeric(numbers))
  numbers[3] < sum(numbers[-3])
}

sum(purrr::map_lgl(input, valid_triangle))
[1] 1050
0.183 sec elapsed

Part 2

input <- readLines("2016/03-input")

numbers <- unlist(stringr::str_extract_all(input, "[0-9]+"))

numbers <- matrix(as.numeric(t(matrix(as.numeric(numbers),
                                      byrow = FALSE, nrow = 3))),
                  byrow = TRUE, ncol = 3)

valid_triangle <- function(x) {
  x <- sort(as.numeric(x))
  x[3] < sum(x[-3])
}

sum(apply(numbers, 1, valid_triangle))
[1] 1921
0.143 sec elapsed

Day 4

Part 1

input <- readLines("2016/04-input")

decoy_value <- function(x) {
  name <- stringr::str_extract(x, "[a-z\\-]+")
  name <- stringr::str_extract_all(name, "[a-z]")[[1]]

  checksum <- stringr::str_extract(x, "\\[.+")
  checksum <- stringr::str_extract(checksum, "[a-z]+")

  sector_id <- as.numeric(stringr::str_extract(x, "[0-9]+"))

  is_real <- paste(names(sort(table(name), decreasing = TRUE)[1:5]), collapse = "") == checksum

  sector_id * is_real
}

sum(purrr::map_dbl(input, decoy_value))
[1] 278221
0.529 sec elapsed

Part 2

input <- readLines("2016/04-input")

decoy_value <- function(x) {
  name <- stringr::str_extract(x, "[a-z\\-]+")
  name <- stringr::str_extract_all(name, "[a-z]")[[1]]

  checksum <- stringr::str_extract(x, "\\[.+")
  checksum <- stringr::str_extract(checksum, "[a-z]+")

  sector_id <- as.numeric(stringr::str_extract(x, "[0-9]+"))

  is_real <- paste(names(sort(table(name), decreasing = TRUE)[1:5]), collapse = "") == checksum

  sector_id * is_real
}

real_inputs <- input[purrr::map_dbl(input, decoy_value) > 0]

decrypt <- function(x) {
  value <- as.numeric(stringr::str_extract(x, "[0-9]+"))

  shift <- value %% 26

  key <- c(letters[-seq_len(shift)], letters[seq_len(shift)], " ")
  names(key) <- c(letters, "-")

  code <- strsplit(stringr::str_remove(x, "[0-9]+"), "")[[1]]
  paste(key[code], collapse = "")
}

decrypted <- purrr::map_chr(real_inputs, decrypt)

real_inputs[which(stringr::str_detect(decrypted, "north"))]
[1] "ghkmaihex-hucxvm-lmhktzx-267[hmxka]"
0.664 sec elapsed

Day 5

Part 1

input <- "uqwqemis"

i <- 0

md5 <- digest::getVDigest()

password <- character()

repeat {
  i <- i + 1
  hash <- md5(paste0(input, i), serialize = FALSE)
  if (stringr::str_sub(hash, 1, 5) == "00000") {
    password <- c(password, stringr::str_sub(hash, 6, 6))
    cat("found new one at ", i, "\n")
    if (length(password) == 8) break
  }
}

paste(password, collapse = "")
found new one at  4515059 
found new one at  6924074 
found new one at  8038154 
found new one at  13432968 
found new one at  13540621 
found new one at  14095580 
found new one at  14821988 
found new one at  16734551 
[1] "1a3099aa"
322.23 sec elapsed

Part 2

input <- "uqwqemis"

i <- 0

md5 <- digest::getVDigest()

password <- list()

repeat {
  i <- i + 1
  hash <- md5(paste0(input, i), serialize = FALSE)
  if (stringr::str_sub(hash, 1, 5) == "00000") {
    location <- stringr::str_sub(hash, 6, 6)
    if (!(location %in% as.character(0:7))) next
    value <- stringr::str_sub(hash, 7, 7)
    if (!is.null(password[[location]])) next
    password[[location]] <- value

    cat("found new one at ", i, "\n")
    if (length(password) == 8) break
  }
}

paste(password[as.character(0:7)], collapse = "")
found new one at  4515059 
found new one at  8038154 
found new one at  13432968 
found new one at  17743256 
found new one at  19112977 
found new one at  20616595 
found new one at  21658552 
found new one at  26326685 
[1] "694190cd"
487.524 sec elapsed

Day 6

Part 1

input <- readLines("2016/06-input")

mat <- unname(Reduce(rbind, strsplit(input, "")))

paste(apply(mat, 2, function(x) names(sort(table(x), TRUE))[1]), collapse = "")
[1] "umejzgdw"
0.025 sec elapsed

Part 2

input <- readLines("2016/06-input")

mat <- unname(Reduce(rbind, strsplit(input, "")))

paste(apply(mat, 2, function(x) names(sort(table(x), FALSE))[1]), collapse = "")
[1] "aovueakv"
0.028 sec elapsed

Day 7

Part 1

library(stringr)
library(magrittr)

input <- readLines("2016/07-input")

TLS_check <- function(x) {
  outside <- str_replace_all(x, "\\[.+?\\]", " ") %>%
    str_detect("([a-z])((?!\\1)[a-z])\\2\\1")

  inside <- str_extract_all(x, "\\[.+?\\]")[[1]] %>%
    paste(collapse = " ") %>%
    str_detect("([a-z])((?!\\1)[a-z])\\2\\1")


  outside & !inside
}

sum(purrr::map_lgl(input, TLS_check))
[1] 110
0.341 sec elapsed

Part 2

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

input <- readLines("2016/07-input")

str_chars <- function(x) {
  str_split(x, "")[[1]]
}

get_anagram <- function(x, is_rev = FALSE) {
  inds <- dplyr::lead(x, 2) == x
  mids <- dplyr::lead(x, 1) != x
  first <- x %in% letters
  second <- dplyr::lead(x, 1) %in% letters

  res <- map(which(inds & mids & first & second), ~x[.x + 0:1])
  if(is_rev) {
    res <- map(res, rev)
  }

  res
}

SSL_check <- function(x) {
  outside <- str_replace_all(x, "\\[.+?\\]", " ") %>%
    str_chars() %>%
    get_anagram()

  inside <- str_extract_all(x, "\\[.+?\\]") %>%
    .[[1]] %>%
    paste(collapse = "") %>%
    str_chars() %>%
    get_anagram(is_rev = TRUE)

  any(inside %in% outside)
}

sum(purrr::map_lgl(input, SSL_check))
[1] 242
1.268 sec elapsed

Day 8

Part 1

input <- readLines("2016/08-input")

rect <- function(grid, x, y) {
  grid[seq_len(x), seq_len(y)] <- 11
  grid
}

rotate <- function(x, by) {
  len <- length(x)
  x[c(seq(len - by + 1, len), seq(1, len -by))]
}

rotate_column <- function(grid, column, by) {
  grid[, column] <- rotate(grid[, column], by)
  grid
}

rotate_row <- function(grid, column, by) {
  grid[column, ] <- rotate(grid[column, ], by)
  grid
}

grid <- matrix(FALSE, nrow = 6, ncol = 50)

for (i in seq_along(input)) {
  action <- stringr::str_extract(input[i], "(rect|row|column)")
  dims <- as.numeric(stringr::str_extract_all(input[i], "[0-9]+")[[1]])

  if (action == "rect") {
    grid <- rect(grid, dims[2], dims[1])
  } else if (action == "row") {
    grid <- rotate_row(grid, dims[1]+1, dims[2])
  } else if (action == "column") {
    grid <- rotate_column(grid, dims[1]+1, dims[2])
  }
}

sum(grid)
[1] 1331
0.031 sec elapsed

Part 2

library(ggplot2)

input <- readLines("2016/08-input")

rect <- function(grid, x, y) {
  grid[seq_len(x), seq_len(y)] <- 11
  grid
}

rotate <- function(x, by) {
  len <- length(x)
  x[c(seq(len - by + 1, len), seq(1, len -by))]
}

rotate_column <- function(grid, column, by) {
  grid[, column] <- rotate(grid[, column], by)
  grid
}

rotate_row <- function(grid, column, by) {
  grid[column, ] <- rotate(grid[column, ], by)
  grid
}

grid <- matrix(FALSE, nrow = 6, ncol = 50)

for (i in seq_along(input)) {
  action <- stringr::str_extract(input[i], "(rect|row|column)")
  dims <- as.numeric(stringr::str_extract_all(input[i], "[0-9]+")[[1]])

  if (action == "rect") {
    grid <- rect(grid, dims[2], dims[1])
  } else if (action == "row") {
    grid <- rotate_row(grid, dims[1]+1, dims[2])
  } else if (action == "column") {
    grid <- rotate_column(grid, dims[1]+1, dims[2])
  }
}

reshape2::melt(grid) %>%
  ggplot(aes(Var2, -Var1, fill = value)) +
  geom_tile() +
  coord_fixed() +
  theme_void() +
  guides(fill = "none")

0.394 sec elapsed

Day 9

Part 1

library(stringr)
library(magrittr)

input <- readLines("2016/09-input")

decompress <- function(input) {
  output <- character()

  repeat {
    output <- c(output, str_extract(input, "^[A-Z]*"))
    input <- str_remove(input, "^[A-Z]*")

    if (str_count(input) == 0) break

    reps <- str_extract(input, "\\(.+?\\)") %>%
      str_extract_all("[0-9]+") %>%
      .[[1]] %>%
      as.numeric()
    input <- str_remove(input, "\\(.+?\\)")
    output <- c(output, str_sub(input, 1, reps[1]) %>% rep(reps[2]))
    input <- str_remove(input, paste0(".{", reps[1], "}", collapse = ""))

    if (str_count(input) == 0) break

  }

  paste0(output, collapse = "")
}

nchar(decompress(input))
[1] 138735
0.03 sec elapsed

Part 2

library(stringr)

input <- readLines("2016/09-input")

decompress_length <- function(input) {

  output <- numeric()

  repeat {
    output <- c(output, nchar(str_extract(input, "^[A-Z]*")))
    input <- str_remove(input, "^[A-Z]*")

    if (str_count(input) == 0) break

    reps <- str_extract(input, "\\(.+?\\)") %>%
      str_extract_all("[0-9]+") %>%
      .[[1]] %>%
      as.numeric()

    section <- str_remove(input, "\\(.+?\\)") %>%
      str_sub(1, reps[1])

    if (str_detect(section, "\\(.+?\\)")) {
      len <- decompress_length(section)
    } else {
      len <- nchar(section)
    }
    output <- c(output, len * reps[2])

    input <- str_remove(input, "\\(.+?\\)")
    input <- str_remove(input, paste0(".{", reps[1], "}", collapse = ""))

    if (str_count(input) == 0) break

  }

  sum(output)
}

decompress_length(input)
[1] 11125026826
0.382 sec elapsed

Day 10

Part 1

library(stringr)
library(purrr)

input <- readLines("2016/10-input")

int <- as.integer
chr <- as.character

values <- str_subset(input, "^value")
input <- str_subset(input, "^value", negate = TRUE)

info <- list(bot = list(), output = list())

values <- str_match_all(values, "\\d+")

for (value in values) {
  info$bot[[value[2, ]]] <- c(info$bot[[value[2, ]]], int(value[1, ]))
}

num <- str_extract_all(input, "\\d+")
des <- str_extract_all(input, "(bot|output)")

inst <- list()

for (i in seq_along(input)) {
  inst[[num[[i]][1]]] <- list(
    low = list(des = des[[i]][2], value = num[[i]][2]),
    high = list(des = des[[i]][3], value = num[[i]][3])
  )
}

repeat {
  selection <- info$bot[lengths(info$bot) == 2]
  if (length(selection) == 0) break
  if (length(selection) > 1) {
    selection <- selection[1]
  }
  name <- names(selection)
  if (identical(sort(selection[[1]]), c(17L, 61L))) {
    cat(name)
  }

  info[[inst[[name]]$low$des]][[inst[[name]]$low$value]] <-
    c(info[[inst[[name]]$low$des]][[inst[[name]]$low$value]], min(selection[[1]]))

  info[[inst[[name]]$high$des]][[inst[[name]]$high$value]] <-
    c(info[[inst[[name]]$high$des]][[inst[[name]]$high$value]], max(selection[[1]]))

  info$bot[[name]] <- NULL
}
27
0.045 sec elapsed

Part 2

library(stringr)
library(purrr)

input <- readLines("2016/10-input")

int <- as.integer
chr <- as.character

values <- str_subset(input, "^value")
input <- str_subset(input, "^value", negate = TRUE)

info <- list(bot = list(), output = list())

values <- str_match_all(values, "\\d+")

for (value in values) {
  info$bot[[value[2, ]]] <- c(info$bot[[value[2, ]]], int(value[1, ]))
}

num <- str_extract_all(input, "\\d+")
des <- str_extract_all(input, "(bot|output)")

inst <- list()

for (i in seq_along(input)) {
  inst[[num[[i]][1]]] <- list(
    low = list(des = des[[i]][2], value = num[[i]][2]),
    high = list(des = des[[i]][3], value = num[[i]][3])
  )
}

repeat {
  selection <- info$bot[lengths(info$bot) == 2]
  if (length(selection) == 0) break
  if (length(selection) > 1) {
    selection <- selection[1]
  }
  name <- names(selection)
  if (identical(sort(selection[[1]]), c(17L, 61L))) {
    cat(name)
  }

  info[[inst[[name]]$low$des]][[inst[[name]]$low$value]] <-
    c(info[[inst[[name]]$low$des]][[inst[[name]]$low$value]], min(selection[[1]]))

  info[[inst[[name]]$high$des]][[inst[[name]]$high$value]] <-
    c(info[[inst[[name]]$high$des]][[inst[[name]]$high$value]], max(selection[[1]]))

  info$bot[[name]] <- NULL
}

info$output[["0"]] * info$output[["1"]] * info$output[["2"]]
27
[1] 13727
0.046 sec elapsed

Day 11

Day 12

Part 1

input <- readLines("2016/12-input")

reg <- c(a = 0, b = 0, c = 0, d = 0)

index <- 1
input_len <- length(input)


get_value <- function(values, reg) {
  check_val <- values[2]
  if (check_val %in% c("a", "b", "c", "d")) {
    check_val <- reg[values[2]]
  } else {
    check_val <- as.integer(check_val)
  }
  check_val
}

repeat {
  command <- substr(input[index], 1, 3)
  values <- strsplit(input[index], " ")[[1]]

  if (command == "cpy") {
    reg[values[3]] <- get_value(values, reg)
    index <- index + 1
  } else if (command == "inc") {
    reg[values[2]] <- reg[values[2]] + 1
    index <- index + 1
  } else if (command == "dec") {
    reg[values[2]] <- reg[values[2]] - 1
    index <- index + 1
  } else if (command == "jnz") {

    check_val <- get_value(values, reg)
    if (check_val != 0) {
      index <- index + as.integer(values[3])
    } else {
      index <- index + 1
    }
  }
  if (index > input_len) break
  reg
}

reg[["a"]]
[1] 318009
9.467 sec elapsed

Part 2

input <- readLines("2016/12-input")

reg <- c(a = 0, b = 0, c = 1, d = 0)

index <- 1
input_len <- length(input)

inst <- strsplit(input, " ")

get_value <- function(values, reg) {
  check_val <- values[2]
  if (check_val %in% c("a", "b", "c", "d")) {
    check_val <- reg[values[2]]
  } else {
    check_val <- as.integer(check_val)
  }
  check_val
}

repeat {
  command <- inst[[index]][1]
  values <- inst[[index]]

  if (command == "cpy") {
    reg[values[3]] <- get_value(values, reg)
    index <- index + 1
  } else if (command == "inc") {
    reg[values[2]] <- reg[values[2]] + 1
    index <- index + 1
  } else if (command == "dec") {
    reg[values[2]] <- reg[values[2]] - 1
    index <- index + 1
  } else if (command == "jnz") {

    check_val <- get_value(values, reg)
    if (check_val != 0) {
      index <- index + as.integer(values[3])
    } else {
      index <- index + 1
    }
  }
  if (index > input_len) break
  reg
}

reg[["a"]]
[1] 9227663
72.035 sec elapsed

Day 13

Part 1

code <- function(x, y) x*x + 3*x + 2*x*y + y + y*y

number <- 1352
room <- function(x, y, number) {
  sum(intToBits(code(x, y) + number) == 1) %% 2
}

size <- 75
maze <- matrix(nrow = size, ncol = size)
maze[2, 2] <- 0 # 0-index

for (x in seq_len(size-1)) {
  for (y in seq_len(size-1)) {
    if (room(x-1, y-1, number) == 1) { # 0-index
      maze[x, y] <- Inf
    }
  }
}

around <- function(x, y) {
  list(
    list(x = x + 0, y = y + 1),
    list(x = x + 1, y = y + 0),
    list(x = x + 0, y = y - 1),
    list(x = x - 1, y = y + 0)
  )
}

validate <- function(l, m) {

  valid <- purrr::map_lgl(l, ~.x$x <= (size-1) && .x$y <= (size-1) && .x$x >= 1 && .x$y >= 1 && is.na(m[.x$x, .x$y]))

  l <- l[valid]
  l
}

append <- function(x, y) {
  c(y, x)
}

find_lowest <- function(place, maze) {
  neighbors <- around(place$x, place$y)
  values <- purrr::map_dbl(neighbors, ~{
    if (.x$x == 0 || .x$y == 0 || .x$y == size || .x$y == size) return(Inf)
    maze[.x$x, .x$y]
  }
  )
  min(values, na.rm = TRUE)
}

places <- list()

places <- around(2, 2) |> # 0-index
  validate(maze) |>
  append(places)

while (length(places) > 0) {
  lowest <- find_lowest(places[[1]], maze)
  maze[places[[1]]$x, places[[1]]$y] <- lowest + 1

  places <- around(places[[1]]$x, places[[1]]$y) |>
    validate(maze) |>
    append(places)

  places[[1]] <- NULL
}
maze[31 + 1, 39 + 1]# 0-index
[1] 90
0.948 sec elapsed

Part 2

code <- function(x, y) x*x + 3*x + 2*x*y + y + y*y

number <- 1352
room <- function(x, y, number) {
  sum(intToBits(code(x, y) + number) == 1) %% 2
}

size <- 75
maze <- matrix(nrow = size, ncol = size)
maze[2, 2] <- 0 # 0-index

for (x in seq_len(size-1)) {
  for (y in seq_len(size-1)) {
    if (room(x-1, y-1, number) == 1) { # 0-index
      maze[x, y] <- Inf
    }
  }
}

around <- function(x, y) {
  list(
    list(x = x + 0, y = y + 1),
    list(x = x + 1, y = y + 0),
    list(x = x + 0, y = y - 1),
    list(x = x - 1, y = y + 0)
  )
}

validate <- function(l, m) {

  valid <- purrr::map_lgl(l, ~.x$x <= (size-1) && .x$y <= (size-1) && .x$x >= 1 && .x$y >= 1 && is.na(m[.x$x, .x$y]))

  l <- l[valid]
  l
}

append <- function(x, y) {
  c(y, x)
}

find_lowest <- function(place, maze) {
  neighbors <- around(place$x, place$y)
  values <- purrr::map_dbl(neighbors, ~{
    if (.x$x == 0 || .x$y == 0 || .x$y == size || .x$y == size) return(Inf)
    maze[.x$x, .x$y]
  }
  )
  min(values, na.rm = TRUE)
}

places <- list()

places <- around(2, 2) |> # 0-index
  validate(maze) |>
  append(places)

while (length(places) > 0) {
  lowest <- find_lowest(places[[1]], maze)
  maze[places[[1]]$x, places[[1]]$y] <- lowest + 1

  places <- around(places[[1]]$x, places[[1]]$y) |>
    validate(maze) |>
    append(places)

  places[[1]] <- NULL
}

sum(maze <= 50 & is.finite(maze))
[1] 135
0.981 sec elapsed

Day 14

Part 1

library(stringr)
library(purrr)

md5 <- digest::getVDigest()

salt <- "ngcjuoqr"

keys <- c()
i <- 1
repeat {
  hash <- md5(paste0(salt, i), serialize = FALSE)
  if (str_detect(hash, "(.)\\1{2,}")) {
    pattern <- str_extract(hash, "(.)\\1{2,}") |>
      str_sub(1, 1) |>
      strrep(5)

    if (any(map_lgl(i + seq_len(1000), ~ str_detect(md5(paste0(salt, .x), serialize = FALSE), pattern)))) {
      keys <- c(keys, i)
      cat(length(keys), ": ", i, "\n", sep = "")
    }
  }

  if (length(keys) == 64) break
  i <- i + 1
}
i
1: 75
2: 94
3: 142
4: 143
5: 203
6: 278
7: 647
8: 852
9: 911
10: 988
11: 1015
12: 1069
13: 1076
14: 1088
15: 1138
16: 1228
17: 1233
18: 1652
19: 1951
20: 2011
21: 2022
22: 2032
23: 2104
24: 2105
25: 2229
26: 2242
27: 2271
28: 2369
29: 2372
30: 2553
31: 2817
32: 3382
33: 3402
34: 3546
35: 3620
36: 3637
37: 3654
38: 4063
39: 4266
40: 7360
41: 7386
42: 7712
43: 7755
44: 10792
45: 10797
46: 10959
47: 10979
48: 11598
49: 11639
50: 11644
51: 11962
52: 11986
53: 12156
54: 12291
55: 14651
56: 14833
57: 15133
58: 15265
59: 18292
60: 18378
61: 18464
62: 18473
63: 18577
64: 18626
[1] 18626
44.139 sec elapsed

Part 2

Day 15

Part 1

input <- readLines("2016/15-input")

input <- input |> stringr::str_match_all("\\d+")

n_pos <- purrr::map_int(input, ~as.integer(.x[2, ]))
pos <- purrr::map_int(input, ~as.integer(.x[4, ]))

i <- 0
repeat {
  if (all((pos + seq_along(pos) + i) %% n_pos == 0)) break
  i <- i + 1
}
i
[1] 16824
0.03 sec elapsed

Part 2

Day 16

Part 1

input <- "10111100110001111"

a <- c("1" = T, "0" = F)[strsplit(input, "")[[1]]]

len <- 272

while (length(a) < len) {
  a <- c(a, FALSE, !rev(a))
}
a <- a[seq_len(len)]

is_even <- function(x) (x %% 2) == 0
is_odd <- function(x) (x %% 2) == 1

repeat {
  if (is_odd(length(a))) {
    break
  }

  a <- purrr::map_lgl(
    split(a, rep(seq_len(length(a)/2), each = 2)),
    ~ .x[1] == .x[2]
  )
}

paste0(as.integer(a), collapse = "")
[1] "11100110111101110"
0.009 sec elapsed

Part 2

input <- "10111100110001111"

a <- c("1" = T, "0" = F)[strsplit(input, "")[[1]]]

len <- 35651584

while (length(a) < len) {
  a <- c(a, FALSE, !rev(a))
}
a <- a[seq_len(len)]

is_even <- function(x) (x %% 2) == 0
is_odd <- function(x) (x %% 2) == 1

repeat {
  if (is_odd(length(a))) {
    break
  }

  a <- purrr::map_lgl(
    split(a, rep(seq_len(length(a)/2), each = 2)),
    ~ .x[1] == .x[2]
  )
}

paste0(as.integer(a), collapse = "")
[1] "10001101010000101"
108.509 sec elapsed

Day 17

Day 18

Part 1

input <- "^.^^^.^..^....^^....^^^^.^^.^...^^.^.^^.^^.^^..^.^...^.^..^.^^.^..^.....^^^.^.^^^..^^...^^^...^...^."
rows <- 40

tiles <- strsplit(input, "")[[1]] == "^"

room <- matrix(FALSE, nrow = rows, ncol = length(tiles) + 2)

room[1, seq_along(tiles) + 1] <- tiles

for (row in seq(2, nrow(room))) {
  for (col in seq(2, ncol(room) - 1)) {
    parent <- room[row - 1, -1:1 + col]

    if (
      identical(c(T, T, F), parent) ||
      identical(c(F, T, T), parent) ||
      identical(c(T, F, F), parent) ||
      identical(c(F, F, T), parent)
    ) {
      room[row, col] <- TRUE
    }
  }
}

sum(!room[, seq_along(tiles) + 1])
[1] 1926
0.02 sec elapsed

Part 2

input <- "^.^^^.^..^....^^....^^^^.^^.^...^^.^.^^.^^.^^..^.^...^.^..^.^^.^..^.....^^^.^.^^^..^^...^^^...^...^."
rows <- 400000

tiles <- strsplit(input, "")[[1]] == "^"

room <- matrix(FALSE, nrow = rows, ncol = length(tiles) + 2)

room[1, seq_along(tiles) + 1] <- tiles

for (row in seq(2, nrow(room))) {
  for (col in seq(2, ncol(room) - 1)) {
    parent <- room[row - 1, -1:1 + col]

    if (
      identical(c(T, T, F), parent) ||
      identical(c(F, T, T), parent) ||
      identical(c(T, F, F), parent) ||
      identical(c(F, F, T), parent)
    ) {
      room[row, col] <- TRUE
    }
  }
}

sum(!room[, seq_along(tiles) + 1])
[1] 19986699
112.207 sec elapsed

Day 19

Part 1

n <- 3004953
2 * (n - 2^(floor(log2(n)))) + 1
[1] 1815603
0.003 sec elapsed

Part 2

fun <- function(n) {
  parts <- seq_len(n) |> as.character()

  repeat {
    parts <- parts[-floor(length(parts) / 2 + 1)]
    if (length(parts) == 1) break
    parts <- parts[c(seq(2, length(parts)), 1)]
  }
  parts
}

which(purrr::map_chr(2:1000, fun) == "1")

3 ^ seq(0, 14)

3004953-1594323
[1] 1410630
8.672 sec elapsed

Day 20

Part 1

input <- readr::read_delim("2016/20-input", delim = "-", col_names = c("min", "max"))

min_target <- 0
max_target <- 4294967295

number <- 0

repeat {
  cond <- which(input$min <= min_target)
  if (length(cond) == 0) break
  cond_max <- input$max[cond]
  min_target <- min(cond_max) + 1
  input <- input[-cond[min(cond_max) == cond_max], ]
}

min_target
[1] 23923783
0.425 sec elapsed

Part 2

input <- readr::read_delim("2016/20-input", delim = "-", col_names = c("min", "max"))

input <- dplyr::arrange(input, min)

used <- 0
count <- 0

for (i in seq_len(nrow(input))) {
  if (input[i, ]$min > used + 1) {
    count <- count + input[i, ]$min - used - 1
  }
  used <- max(input[i, ]$max, used)
}
count
[1] 125
0.209 sec elapsed

Day 21

Part 1

library(stringr)
int <- as.integer
plus1 <- function(x) x + 1

input <- readLines("2016/21-input")

password <- strsplit("abcdefgh", "")[[1]]
password_len <- length(password)

rotate_left <- function(x, n) {
  c(password[-seq_len(1)], password[seq_len(1)])
}

for (command in input) {
  if (str_detect(command, "^swap position")) {
    pos <- str_extract_all(command, "\\d")[[1]] |> int() |> plus1()
    password[pos] <- rev(password[pos])
  }
  if (str_detect(command, "^swap letter")) {
    letter <- str_sub(command, c(13, 27), c(13, 27))
    pos <- match(letter, password)
    password[pos] <- rev(password[pos])
  }
  if (str_detect(command, "^reverse positions")) {
    pos <- str_extract_all(command, "\\d")[[1]] |> int() |> plus1()
    password[pos[1]:pos[2]] <- rev(password[pos[1]:pos[2]])
  }
  if (str_detect(command, "^rotate left")) {
    shift <- str_extract(command, "\\d") |> int()
    if (shift == 0) next
    password <- c(password[-seq_len(shift)], password[seq_len(shift)])
  }
  if (str_detect(command, "^rotate right")) {
    shift <- str_extract(command, "\\d") |> int()
    if (shift == 0) next
    password <- c(
      rev(rev(password)[seq_len(shift)]),
      rev(rev(password)[-seq_len(shift)])
    )
  }
  if (str_detect(command, "^move position")) {
    pos <- str_extract_all(command, "\\d")[[1]] |> int() |> plus1()
    element <- password[pos[1]]
    password <- password[-pos[1]]
    if (pos[2] == 1) {
      password <- c(element, password)
    } else if (pos[2] == password_len) {
      password <- c(password, element)
    } else
      password <- c(
        password[seq_len(pos[2]-1)],
        element,
        password[seq(pos[2], password_len-1)]
      )
  }
  if (str_detect(command, "^rotate based")) {
    letter <- str_sub(command, 36, 36)
    shift <- match(letter, password)
    shift <- shift
    password <- c(
      rev(rev(password)[seq_len(shift)]),
      rev(rev(password)[-seq_len(shift)])
    )
    if (shift > 4) {
      password <- c(
        rev(rev(password)[seq_len(1)]),
        rev(rev(password)[-seq_len(1)])
      )
    }
  }
}
cat(paste(password, collapse = ""), "\n")
gcedfahb 
0.062 sec elapsed

Part 2

library(stringr)
int <- as.integer
plus1 <- function(x) x + 1

input <- readLines("2016/21-input")

rotate_left <- function(x, n) {
  c(password[-seq_len(1)], password[seq_len(1)])
}

shuffle <- function(password) {
  password <- strsplit(password, "")[[1]]
  password_len <- length(password)
  for (command in input) {
    if (str_detect(command, "^swap position")) {
      pos <- str_extract_all(command, "\\d")[[1]] |> int() |> plus1()
      password[pos] <- rev(password[pos])
    }
    if (str_detect(command, "^swap letter")) {
      letter <- str_sub(command, c(13, 27), c(13, 27))
      pos <- match(letter, password)
      password[pos] <- rev(password[pos])
    }
    if (str_detect(command, "^reverse positions")) {
      pos <- str_extract_all(command, "\\d")[[1]] |> int() |> plus1()
      password[pos[1]:pos[2]] <- rev(password[pos[1]:pos[2]])
    }
    if (str_detect(command, "^rotate left")) {
      shift <- str_extract(command, "\\d") |> int()
      if (shift == 0) next
      password <- c(password[-seq_len(shift)], password[seq_len(shift)])
    }
    if (str_detect(command, "^rotate right")) {
      shift <- str_extract(command, "\\d") |> int()
      if (shift == 0) next
      password <- c(
        rev(rev(password)[seq_len(shift)]),
        rev(rev(password)[-seq_len(shift)])
      )
    }
    if (str_detect(command, "^move position")) {
      pos <- str_extract_all(command, "\\d")[[1]] |> int() |> plus1()
      element <- password[pos[1]]
      password <- password[-pos[1]]
      if (pos[2] == 1) {
        password <- c(element, password)
      } else if (pos[2] == password_len) {
        password <- c(password, element)
      } else
        password <- c(
          password[seq_len(pos[2]-1)],
          element,
          password[seq(pos[2], password_len-1)]
        )
    }
    if (str_detect(command, "^rotate based")) {
      letter <- str_sub(command, 36, 36)
      shift <- match(letter, password)
      shift <- shift
      password <- c(
        rev(rev(password)[seq_len(shift)]),
        rev(rev(password)[-seq_len(shift)])
      )
      if (shift > 4) {
        password <- c(
          rev(rev(password)[seq_len(1)]),
          rev(rev(password)[-seq_len(1)])
        )
      }
    }
  }
  paste(password, collapse = "")
}

expand.grid(letters[1:8], letters[1:8], letters[1:8], letters[1:8], letters[1:8], letters[1:8],letters[1:8], letters[1:8])


library(combinat)

keys <- permn(letters[1:8]) |>
  purrr::map_chr(paste, collapse = "") |>
  purrr::map_chr(shuffle)

permn(letters[1:8])[[which(keys == "fbgdceah")]] |> paste(collapse = "")
[1] "hegbdcfa"
536.444 sec elapsed

Day 22

Part 1

library(tidyverse)
input <- readr::read_lines("2016/21-input", skip = 2) %>%
  strsplit(" +") %>%
  purrr::reduce(rbind) %>%
  tibble::as_tibble() %>%
  purrr::set_names(c("Filesystem", "Size", "Used", "Avail", "Use")) %>%
  tidyr::separate(Filesystem, c("tmp", "x", "y"), sep = "-") %>%
  mutate(across(x:y, ~ readr::parse_number(.x) %>% as.integer()))

library(dplyr)
pairs <- expand.grid(x0 = 0:29, y0 = 0:29, x1 = 0:29, y1 = 0:29) %>%
  filter((abs(x0 - x1) == 1) + (abs(y0 - y1) == 1) == 1)

pairs %>%
  left_join(input, by = c("x0" = "x", "y0" = "y")) %>%
  left_join(input, by = c("x1" = "x", "y1" = "y")) %>%
  filter(readr::parse_number(Used.x) <= readr::parse_number(Avail.y))
 [1] x0      y0      x1      y1      tmp.x   Size.x  Used.x  Avail.x
 [9] Use.x   tmp.y   Size.y  Used.y  Avail.y Use.y  
<0 rows> (or 0-length row.names)
0.681 sec elapsed

Day 23

Day 24

Day 25