2022-08: Treetop Tree House

library(mistlecode)
dt <- fread("input.txt", header = FALSE)

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