AdventOfCode > 2022
Part 1: How many positions does the tail of the rope visit at least once?
I manually downloaded my personal day 9 input file as a logged user, and here I get the data in a more appropriate shape.
── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
✔ ggplot2 3.4.0 ✔ purrr 0.3.5
✔ tibble 3.1.8 ✔ dplyr 1.0.10
✔ tidyr 1.2.1 ✔ stringr 1.5.0.9000
✔ readr 2.1.3 ✔ forcats 0.5.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
data <- here::here("2022/09_input") %>%
read_csv(
col_names = c("line"),
show_col_types = FALSE
)
data
# A tibble: 2,000 × 1
line
<chr>
1 D 2
2 U 2
3 L 2
4 D 2
5 L 2
6 D 2
7 L 1
8 D 2
9 U 1
10 L 1
# … with 1,990 more rows
We expect 13 as a response of this input:
test <- tribble(
~line,
"R 4",
"U 4",
"L 3",
"D 1",
"R 4",
"D 1",
"L 5",
"R 2"
)
test
# A tibble: 8 × 1
line
<chr>
1 R 4
2 U 4
3 L 3
4 D 1
5 R 4
6 D 1
7 L 5
8 R 2
moves <- list(
"R" = c(1, 0),
"L" = c(-1, 0),
"U" = c(0, -1),
"D" = c(0, 1)
)
find_position <- function(status) {
dx <- status[[1]][1] - status[[2]][1];
dy <- status[[1]][2] - status[[2]][2];
c(dx, dy)
}
update_status <- function(status, position) {
dx <- position[1]
dy <- position[2]
if (abs(dx) > 1) {
if (dx > 0) status[[2]][1] <- status[[2]][1] + 1
if (dx < 0) status[[2]][1] <- status[[2]][1] - 1
if (dy > 0) status[[2]][2] <- status[[2]][2] + 1
if (dy < 0) status[[2]][2] <- status[[2]][2] - 1
} else if (abs(dy) > 1) {
if (dy > 0) status[[2]][2] <- status[[2]][2] + 1
if (dy < 0) status[[2]][2] <- status[[2]][2] - 1
if (dx > 0) status[[2]][1] <- status[[2]][1] + 1
if (dx < 0) status[[2]][1] <- status[[2]][1] - 1
}
status
}
move_rope <- function(input) {
data <- pull(input) %>% str_split(" ")
result <- list()
status <- list()
status <- append(status, list(c(0, 0)))
status <- append(status, list(c(0, 0)))
for (motion in seq_along(data)) {
direction <- data[[motion]][1]
steps <- as.integer(data[[motion]][2])
for (i in 1:steps) {
# print(paste0("motion ", motion," direction ", direction," steps ", i, "/", steps))
status[[1]] <- c(
status[[1]][1] + moves[[direction]][1],
status[[1]][2] + moves[[direction]][2]
)
position <- find_position(status)
status <- update_status(status, position)
result <- append(result, status[2])
}
}
result
}
moved <- move_rope(test)
moved %>% map_chr(~paste(.x, collapse=",")) %>% unique() %>% length()
Here’s the result for my input:
tictoc::tic("part1")
moved <- move_rope(data)
moved %>% map_chr(~paste(.x, collapse=",")) %>% unique() %>% length()
Part 2: Simulate your complete series of motions on a larger rope with ten knots. How many positions does the tail of the rope visit at least once?
find_status <- function(status, rope_size) {
for (knot in 2:rope_size) {
dx <- status[[knot - 1]][1] - status[[knot]][1];
dy <- status[[knot - 1]][2] - status[[knot]][2];
if (abs(dx) > 1) {
if (dx > 0) status[[knot]][1] <- status[[knot]][1] + 1
if (dx < 0) status[[knot]][1] <- status[[knot]][1] - 1
if (dy > 0) status[[knot]][2] <- status[[knot]][2] + 1
if (dy < 0) status[[knot]][2] <- status[[knot]][2] - 1
} else if (abs(dy) > 1) {
if (dy > 0) status[[knot]][2] <- status[[knot]][2] + 1
if (dy < 0) status[[knot]][2] <- status[[knot]][2] - 1
if (dx > 0) status[[knot]][1] <- status[[knot]][1] + 1
if (dx < 0) status[[knot]][1] <- status[[knot]][1] - 1
}
}
status
}
move_rope <- function(input, rope_size) {
data <- pull(input) %>% str_split(" ")
result <- list()
status <- list()
for (zzz in 1:rope_size) {
status <- append(status, list(c(0, 0)))
}
for (motion in seq_along(data)) {
direction <- data[[motion]][1]
steps <- as.integer(data[[motion]][2])
for (i in 1:steps) {
status[[1]] <- c(
status[[1]][1] + moves[[direction]][1],
status[[1]][2] + moves[[direction]][2]
)
status <- find_status(status, rope_size)
result <- append(result, status[rope_size])
}
}
result
}
move_rope(test, 10) %>%
map_chr(~paste(.x, collapse=",")) %>%
unique() %>%
length()
move_rope(data, 10) %>%
map_chr(~paste(.x, collapse=",")) %>%
unique() %>%
length()
Solution
library(tidyverse)
data <-
here::here("2022/09_input") %>%
read_csv(
col_names = c("line"),
show_col_types = FALSE
)
moves <- list(
"R" = c(1, 0),
"L" = c(-1, 0),
"U" = c(0, -1),
"D" = c(0, 1)
)
find_status <- function(status, rope_size) {
for (knot in 2:rope_size) {
dx <- status[[knot - 1]][1] - status[[knot]][1];
dy <- status[[knot - 1]][2] - status[[knot]][2];
if (abs(dx) > 1) {
if (dx > 0) status[[knot]][1] <- status[[knot]][1] + 1
if (dx < 0) status[[knot]][1] <- status[[knot]][1] - 1
if (dy > 0) status[[knot]][2] <- status[[knot]][2] + 1
if (dy < 0) status[[knot]][2] <- status[[knot]][2] - 1
} else if (abs(dy) > 1) {
if (dy > 0) status[[knot]][2] <- status[[knot]][2] + 1
if (dy < 0) status[[knot]][2] <- status[[knot]][2] - 1
if (dx > 0) status[[knot]][1] <- status[[knot]][1] + 1
if (dx < 0) status[[knot]][1] <- status[[knot]][1] - 1
}
}
status
}
move_rope <- function(input, rope_size) {
data <- pull(input) %>% str_split(" ")
result <- list()
status <- list()
for (zzz in 1:rope_size) {
status <- append(status, list(c(0, 0)))
}
for (motion in seq_along(data)) {
direction <- data[[motion]][1]
steps <- as.integer(data[[motion]][2])
for (i in 1:steps) {
status[[1]] <- c(
status[[1]][1] + moves[[direction]][1],
status[[1]][2] + moves[[direction]][2]
)
status <- find_status(status, rope_size)
result <- append(result, status[rope_size])
}
}
result
}
tictoc::tic("part1")
move_rope(data, 2) %>%
map_chr(~paste(.x, collapse=",")) %>%
unique() %>%
length()
tictoc::tic("part2")
move_rope(data, 10) %>%
map_chr(~paste(.x, collapse=",")) %>%
unique() %>%
length()