AoC 2020 (R)
Sonia Mitchell
2022-01-04
2020-R.Rmd
Day 12: Rain Risk
Part 1
# Read in data ------------------------------------------------------------
day12input <- function(path) {
readLines(path) |>
data.frame() |>
setNames("dat") |>
tidyr::separate("dat", into = c("inst", "value"),
sep = "(?<=[A-Za-z])(?=[0-9])") |>
dplyr::mutate(value = as.numeric(value))
}
test <- here("inst", "2020", "day12-test.txt") |>
day12input()
dat <- here("inst", "2020", "day12.txt") |>
day12input()
# Define functions --------------------------------------------------------
evasive_actions <- R6::R6Class("ferry", list(
ship = NULL,
rot = NULL,
initialize = function() {
self$ship <- c(0, 0)
self$rot <- 90
invisible(self)
},
print = function(...) {
cat("ship:", self$ship, "/n")
invisible(self)
},
move = function(inst, value) {
switch(inst,
"N" = {self$ship[2] <- self$ship[2] + value},
"S" = {self$ship[2] <- self$ship[2] - value},
"E" = {self$ship[1] <- self$ship[1] + value},
"W" = {self$ship[1] <- self$ship[1] - value},
"L" = {tmp <- self$rot - value
self$rot <- ifelse(tmp < 0, 360 + tmp, tmp)},
"R" = {tmp <- self$rot + value
self$rot <- ifelse(tmp >= 360, tmp - 360, tmp)},
"F" = self$forward(value))
invisible(self)
},
forward = function(value) {
if (self$rot == 0) {
self$move("N", value)
} else if (self$rot == 90) {
self$move("E", value)
} else if (self$rot == 180) {
self$move("S", value)
} else if (self$rot == 270) {
self$move("W", value)
}
invisible(self)
}
))
evade <- function(dat) {
ferry <- evasive_actions$new()
# Perform evasive action
for (i in seq_len(nrow(dat))) {
ferry$move(dat$inst[i], dat$value[i])
}
# Calculate Manhattan distance
rbind(c(0, 0), ferry$ship) |>
dist(method = "manhattan") |>
c()
}
# Take evasive actions ----------------------------------------------------
assertthat::assert_that(evade(test) == 25)
## [1] TRUE
# What is the Manhattan distance between that location and the ship's
# starting position?
evade(dat)
## [1] 2270
0.129 sec.
Part 2
# Define functions --------------------------------------------------------
follow_waypoint <- R6::R6Class("waypoint", list(
ship = NULL,
waypoint = NULL,
initialize = function() {
self$ship <- c(0, 0)
self$waypoint <- c(10, 1)
invisible(self)
},
print = function(...) {
cat("ship:", self$ship)
cat("\nwaypoint:", self$waypoint, "\n")
invisible(self)
},
move = function(inst, value) {
switch(inst,
"N" = {self$waypoint[2] <- self$waypoint[2] + value},
"S" = {self$waypoint[2] <- self$waypoint[2] - value},
"E" = {self$waypoint[1] <- self$waypoint[1] + value},
"W" = {self$waypoint[1] <- self$waypoint[1] - value},
"L" = self$rotate(-value),
"R" = self$rotate(value),
"F" = self$forward(value))
invisible(self)
},
rotate = function(value) {
rad <- value * pi / 180
x <- self$waypoint[1]
y <- self$waypoint[2]
newX <- x * cos(rad) + y * sin(rad)
newY <- y * cos(rad) - x * sin(rad)
self$waypoint <- c(newX, newY)
invisible(self)
},
forward = function(value) {
self$ship[1] <- self$ship[1] + (self$waypoint[1] * value)
self$ship[2] <- self$ship[2] + (self$waypoint[2] * value)
invisible(self)
}
))
evade2 <- function(dat) {
ferry <- follow_waypoint$new()
# Perform evasive action
for (i in seq_len(nrow(dat))) {
ferry$move(dat$inst[i], dat$value[i])
}
# Calculate Manhattan distance
rbind(c(0, 0), ferry$ship) |>
dist(method = "manhattan") |>
c()
}
# Take evasive actions ----------------------------------------------------
assertthat::assert_that(evade2(test) == 286)
## [1] TRUE
# What is the Manhattan distance between that location and the ship's
# starting position?
evade2(dat)
## [1] 138669
0.042 sec.