2022-05: Supply Stacks

library(tidyverse)
── 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.4.1 
✔ readr   2.1.3      ✔ forcats 0.5.2 
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(data.table)

Attaching package: 'data.table'

The following objects are masked from 'package:dplyr':

    between, first, last

The following object is masked from 'package:purrr':

    transpose

This was a big mess. It took me forever to read in the input and I eventually stumbled upon reaf_fwf because I couldn’t remember what a fixed-width file was. I kept looking for delimited readers and tried all sorts of crazy things.

Note

The do_part function was added after completion so that the code isn’t too long when sharing since it’s such a minor difference.

file_name <- "input.txt"
move <- function(piles, i, ins, part) {
  moveN <- ins$X2[i]
  fromN <- ins$X3[i]
  toN <- ins$X4[i]
  
  from <- piles[[fromN]]
  to <- piles[[toN]]
  
  if (part == 1) { to <- c(rev(from[1:moveN]), to) }
  else if (part == 2) { to <- c(from[1:moveN], to) }
  from <- tail(from, -moveN)
  
  piles[[fromN]] <- from[!is.na(from)]
  piles[[toN]] <- to[!is.na(to)]
  
  return(piles)
}

do_part <- function(part) {
  dt <- readLines(file_name)
  piles <- read_fwf(file = file_name, na = "  ", n_max = which(dt == "") - 2)
  
  piles <- piles |>
    as.matrix()
  piles <-
    lapply(seq_len(ncol(piles)), \(i) piles[, i]) |>
    lapply(\(x) str_extract(x[x != ""], "\\w"))
  
  ins <-
    readLines(file_name) |>
    tail(-(which(dt == "") - 1)) |>
    str_match_all("move (\\d*) from (\\d*) to (\\d*)") %>%
    do.call(rbind, .) |>
    data.frame() |>
    lapply(as.numeric) |>
    data.frame()
  
  for (i in 1:nrow(ins)) {
    piles <- move(piles, i, ins, part = part)
  }
  piles |>
    lapply(\(x) head(x, 1)) |>
    unlist() |>
    paste(collapse = "")
}

Part 1

Once I had the input in, it was relatively smooth sailing. I missed the part in part 1 where the boxes move one by one (oh part 2, how I wish I knew you then…) but once I had that fixed, I was looking pretty good. I got the test input working but then the real input wasn’t working. I eventually realized that my regex \\d was missing any numbers greater than 9 once that was fixed, everything else was pretty easy.

do_part(1)
Rows: 8 Columns: 9
── Column specification ────────────────────────────────────────────────────────

chr (9): X1, X2, X3, X4, X5, X6, X7, X8, X9

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Warning in lapply(data.frame(str_match_all(tail(readLines(file_name), -(which(dt
== : NAs introduced by coercion
[1] "ZBDRNPMVH"

Part 2

After firing off a celebratory text message, I read part 2, deleted my rev and was done in 52 seconds!

do_part(2)
Rows: 8 Columns: 9
── Column specification ────────────────────────────────────────────────────────

chr (9): X1, X2, X3, X4, X5, X6, X7, X8, X9

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Warning in lapply(data.frame(str_match_all(tail(readLines(file_name), -(which(dt
== : NAs introduced by coercion
[1] "WDLPFNNNB"