R/day11.R

# book-keeping

#' Day 11: Chronal Charge
#'
#' [Chronal Charge](https://adventofcode.com/2018/day/11)
#'
#' @name day11
#' @rdname day11
#' @details
#'
#' **Part One**
#'
#' You watch the Elves and their sleigh fade into the distance as they head
#' toward the North Pole.
#'
#' Actually, you're the one fading. The [falling
#' sensation]{title="wheeeeeeeeeeeeeeeeee"} returns.
#'
#' The low fuel warning light is illuminated on your wrist-mounted device.
#' Tapping it once causes it to project a hologram of the situation: a
#' *300x300* grid of fuel cells and their current power levels, some
#' negative. You're not sure what negative power means in the context of
#' time travel, but it can't be good.
#'
#' Each fuel cell has a coordinate ranging *from 1 to 300* in both the X
#' (horizontal) and Y (vertical) direction. In `X,Y` notation, the top-left
#' cell is `1,1`, and the top-right cell is `300,1`.
#'
#' The interface lets you select *any 3x3 square* of fuel cells. To
#' increase your chances of getting to your destination, you decide to
#' choose the 3x3 square with the *largest total power*.
#'
#' The power level in a given fuel cell can be found through the following
#' process:
#'
#' -   Find the fuel cell's *rack ID*, which is its *X coordinate plus 10*.
#' -   Begin with a power level of the *rack ID* times the *Y coordinate*.
#' -   Increase the power level by the value of the *grid serial number*
#'     (your puzzle input).
#' -   Set the power level to itself multiplied by the *rack ID*.
#' -   Keep only the *hundreds digit* of the power level (so `12345`
#'     becomes `3`; numbers with no hundreds digit become `0`).
#' -   *Subtract 5* from the power level.
#'
#' For example, to find the power level of the fuel cell at `3,5` in a grid
#' with serial number `8`:
#'
#' -   The rack ID is `3 + 10 = 13`.
#' -   The power level starts at `13 * 5 = 65`.
#' -   Adding the serial number produces `65 + 8 = 73`.
#' -   Multiplying by the rack ID produces `73 * 13 = 949`.
#' -   The hundreds digit of `949` is `9`.
#' -   Subtracting 5 produces `9 - 5 = 4`.
#'
#' So, the power level of this fuel cell is `4`.
#'
#' Here are some more example power levels:
#'
#' -   Fuel cell at  `122,79`, grid serial number `57`: power level `-5`.
#' -   Fuel cell at `217,196`, grid serial number `39`: power level  `0`.
#' -   Fuel cell at `101,153`, grid serial number `71`: power level  `4`.
#'
#' Your goal is to find the 3x3 square which has the largest total power.
#' The square must be entirely within the 300x300 grid. Identify this
#' square using the `X,Y` coordinate of its *top-left fuel cell*. For
#' example:
#'
#' For grid serial number `18`, the largest total 3x3 square has a top-left
#' corner of `33,45` (with a total power of `29`); these fuel cells appear
#' in the middle of this 5x5 region:
#'
#'     -2  -4   4   4   4
#'     -4   4   4   4  -5
#'      4   3   3   4  -4
#'      1   1   2   4  -3
#'     -1   0   2  -5  -2
#'
#' For grid serial number `42`, the largest 3x3 square's top-left is
#' `21,61` (with a total power of `30`); they are in the middle of this
#' region:
#'
#'     -3   4   2   2   2
#'     -4   4   3   3   4
#'     -5   3   3   4  -4
#'      4   3   3   4  -3
#'      3   3   3  -5  -1
#'
#' *What is the `X,Y` coordinate of the top-left fuel cell of the 3x3
#' square with the largest total power?*
#'
#' **Part Two**
#'
#' *(Use have to manually add this yourself.)*
#'
#' *(Try using `convert_clipboard_html_to_roxygen_md()`)*
#'
#' @param x some data
#' @return For Part One, `f11a(x)` returns .... For Part Two,
#'   `f11b(x)` returns ....
#' @export
#' @examples
#' f11a()
#' f11b()
pool_power_cells <- function(mat, pool_span, fun = sum) {
  # The pools should not extend outside of the original grid.
  # If the pool is 10 units wide and the matrix is 25 cells wide, then the
  # bottom right cornder of the sums should be 16,16.
  new_span <- ncol(mat) - pool_span + 1
  cols <- rep(1:new_span, new_span)
  rows <- rep(1:new_span, each = new_span)

  # Pools are located at the x,y coordinate plus some offsets.
  # The 3x3 pool at 2,2 has xs at 2 + c(0, 1, 2)
  offsets <- seq(0, by = 1, length.out = pool_span)

  f <- function(col, row) {
    fun(mat[row + offsets, col + offsets])
  }

  results <- purrr::map2(cols, rows, f) %>%
    purrr::flatten_dbl() %>%
    matrix(
      ncol = new_span,
      nrow = new_span,
      byrow = TRUE)

  item <- which.max(results)
  list(
    # Yeah, I know this is confusing. I think which.max() is column-major?
    x = rows[item],
    y = cols[item],
    power = results[item],
    span = pool_span
  )
}





#' @rdname day11
#' @export
compute_cell_power_level <- function(x, y, serial_number) {
  rack_id <- x + 10
  power_level <- (rack_id * y + serial_number) * rack_id
  hundredth <- (power_level %% 1000) %/% 100
  hundredth - 5
}


#' @rdname day11
#' @export
create_power_cell_matrix <- function(span, serial_number) {
  coords <- enumerate_x_y_coords(span, span)
  m2 <- compute_cell_power_level(coords$x, coords$y, serial_number) %>%
    matrix(ncol = span, byrow = TRUE)
  # m <- matrix(nrow = span, ncol = span)
  # for (x in seq_len(span)) {
  #   for (y in seq_len(span)) {
  #     m[y, x] <- compute_cell_power_level(x, y, serial_number)
  #   }
  # }
  m2
}

enumerate_x_y_coords <- function(span_x, span_y) {
  list(
    x = rep(1:span_x, span_x),
    y = rep(1:span_y, each = span_y)
  )
}

#' @rdname day11
#' @export
search_power_cell_pools <- function(mat, to_search = NULL) {
  if (is.null(to_search)) {
    to_search <- seq_len(nrow(mat))
  }
  purrr::map_dfr(to_search, pool_power_cells, mat = mat)
}
tjmahr/adventofcode18 documentation built on May 24, 2019, 4:10 p.m.