2022-08: Treetop Tree House
Oh no. I always do hate grid based ones.
Part 1
This was a weird one. I’m writing this the day after I wrote the code, and I have no clue what my thought process was. I did it reasonably quickly so I’m not too unhappy with it.
mm <-
dt |>
as.matrix() |>
as.character() |>
str_split("", simplify = TRUE) |>
apply(c(1, 2), as.numeric)
grid <- expand.grid("col" = 1:ncol(mm), "row" = 1:nrow(mm))
m <-
mapply(\(x, y) {
tree <- mm[y, x]
if (x == 1 | x == ncol(mm) | y == 1 | y == nrow(mm)) { return(c(x, y)) }
if (all(mm[(y + 1):nrow(mm), x] < tree, na.rm = TRUE) |
all(mm[1:(y - 1), x] < tree, na.rm = TRUE) |
all(mm[y, 1:(x - 1)] < tree, na.rm = TRUE) |
all(mm[y, (x + 1):ncol(mm)] < tree, na.rm = TRUE)) {
return(c(x, y))
}
}, grid$col, grid$row)
m[!sapply(m, is.null)] %>%
do.call(rbind, .) |>
data.frame() |>
`colnames<-`(c("col", "row")) -> mi
nrow(mi)
[1] 1717
Part 2
This was a mess. I kept trying to be smart about it and wasted so much time. I mostly had trouble working with patterns like [5050]
where the first five can see both the zero and the second five, but not the second zero. This meant that x < 5
ignored the five, and x <= 5
would keep going and read over the remaining zero. Even though I ended up hard-coding everything, I’m rather pleased with how neat it is. I’m sure I could move more of it to functions, but it wouldn’t be too much prettier, if any.
scenic <- matrix(NA, nrow(mm), ncol(mm))
checker <- function(vec, i, tree, dir) {
vec <- detect_index(vec, \(.x) { .x >= tree })
if (dir == -1) { vec <- ifelse(vec == 0, i - 1, vec) }
else { vec <- ifelse(vec == 0, ncol(mm) - i, vec) }
vec
}
mapply(\(y, x) {
tree <- mm[y, x]
up <- NA; down <- NA; left <- NA; right <- NA
if (y == 1) { up <- 0 }; if (y == nrow(mm)) { down <- 0 }
if (x == 1) { left <- 0}; if (x == ncol(mm)) { right <- 0 }
rowMin <- ifelse(y - 1 < 1, 1, y - 1); rowMax <- ifelse(y + 1 > nrow(mm), nrow(mm), y + 1)
colMin <- ifelse(x - 1 < 1, 1, x - 1); colMax <- ifelse(x + 1 > ncol(mm), ncol(mm), x + 1)
yMin <- ifelse(y - 1 < 1, 1, y - 1); yMax <- ifelse(y + 1 > nrow(mm), nrow(mm), y + 1)
xMin <- ifelse(x - 1 < 1, 1, x - 1); xMax <- ifelse(x + 1 > ncol(mm), ncol(mm), x + 1)
if (is.na(up)) { up <- checker(rev(mm[1:yMin, x]), y, tree, -1) }
if (is.na(left)) { left <- checker(rev(mm[y, 1:xMin]), x, tree, -1) }
if (is.na(right)) { right <- checker(mm[y, xMax:ncol(mm)], x, tree, 1) }
if (is.na(down)) { down <- checker(mm[rowMax:nrow(mm), x], y, tree, 1) }
scene <- c(up, left, right, down)
scenic[y, x] <<- prod(scene[scene != 0])
}, grid$row, grid$col) |> invisible()
max(scenic)
[1] 321975