Day 5

AdventOfCode > 2022

Part 1: After the rearrangement procedure completes, what crate ends up on top of each stack?

I manually downloaded my personal day 5 input file as a logged user, and here I get the data in a more appropriate shape.

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.9000
✔ readr   2.1.3          ✔ forcats 0.5.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
data <- 
    read_csv(
        here::here("2022/05_input"),
        col_names = c("lines"),
        show_col_types = FALSE,
        skip_empty_rows = FALSE
    )

data %>% print(n = 11)
# A tibble: 511 × 1
   lines                              
   <chr>                              
 1 [N]             [R]             [C]
 2 [T] [J]         [S] [J]         [N]
 3 [B] [Z]     [H] [M] [Z]         [D]
 4 [S] [P]     [G] [L] [H] [Z]     [T]
 5 [Q] [D]     [F] [D] [V] [L] [S] [M]
 6 [H] [F] [V] [J] [C] [W] [P] [W] [L]
 7 [G] [S] [H] [Z] [Z] [T] [F] [V] [H]
 8 [R] [H] [Z] [M] [T] [M] [T] [Q] [W]
 9 1   2   3   4   5   6   7   8   9  
10 <NA>                               
11 move 3 from 9 to 7                 
# … with 500 more rows

I represent the starting stack status with a list:

stacks <- data %>% 
    filter(str_detect(lines, "\\[")) %>% 
    arrange(-row_number()) %>% 
    separate(lines, into = paste0("c", 1:36), sep = "") %>% 
    pivot_longer(everything()) %>% 
    filter(str_detect(value, "[A-Z]")) %>% 
    pivot_wider(
        names_from = name, values_from = value, values_fn = list
    ) %>% 
    map(~ .x[[1]]) %>% 
    unname()

stacks
[[1]]
[1] "R" "G" "H" "Q" "S" "B" "T" "N"

[[2]]
[1] "H" "S" "F" "D" "P" "Z" "J"

[[3]]
[1] "Z" "H" "V"

[[4]]
[1] "M" "Z" "J" "F" "G" "H"

[[5]]
[1] "T" "Z" "C" "D" "L" "M" "S" "R"

[[6]]
[1] "M" "T" "W" "V" "H" "Z" "J"

[[7]]
[1] "T" "F" "P" "L" "Z"

[[8]]
[1] "Q" "V" "W" "S"

[[9]]
[1] "W" "H" "L" "M" "T" "D" "N" "C"

I represent the rearrangement of movements with a list of tibbles:

extract_next_number <- function(x, pattern) {
    x %>%
        substring(str_locate(x, pattern)[[1]]) %>% 
        str_extract("[0-9]+") %>% 
        as.numeric()
}

moves <- data %>% 
    filter(str_detect(lines, "move")) %>% 
    rowwise() %>% 
    transmute(
        qty = extract_next_number(lines, ""),
        from = extract_next_number(lines, "from"),
        to = extract_next_number(lines, "to"),
    ) 

moves
# A tibble: 501 × 3
# Rowwise: 
     qty  from    to
   <dbl> <dbl> <dbl>
 1     3     9     7
 2     4     4     5
 3     2     4     6
 4     4     7     5
 5     3     7     3
 6     2     5     9
 7     5     6     3
 8     5     9     1
 9     3     8     4
10     3     4     6
# … with 491 more rows

If I move 3 from 1 to 3:

[D]        
[N] [C]    
[Z] [M] [P]
 1   2   3 

It should be:

        [Z]
        [N]
    [C] [D]
    [M] [P]
 1   2   3

I create a helper function and I test the previous example:

stacks2 <- list(
    c("Z","N", "D"),
    c("M","C"),
    c("P")
)

make_move <- function(x, qty, from, to) {
    to_move <- rev(tail(x[[from]], qty))
    x[[from]] <- head(x[[from]], -qty)
    x[[to]] <- c(x[[to]], to_move)
    x
}
stacks2
[[1]]
[1] "Z" "N" "D"

[[2]]
[1] "M" "C"

[[3]]
[1] "P"
stacks2 %>% make_move(3, 1, 3)
[[1]]
character(0)

[[2]]
[1] "M" "C"

[[3]]
[1] "P" "D" "N" "Z"

Here the full code:

library(tidyverse)

data <- 
    read_csv(
        here::here("2022/05_input"),
        col_names = c("lines"),
        show_col_types = FALSE,
        skip_empty_rows = FALSE
    )

extract_next_number <- function(x, pattern) {
    x %>%
        substring(str_locate(x, pattern)[[1]]) %>% 
        str_extract("[0-9]+") %>% 
        as.numeric()
}

make_move <- function(x, qty, from, to) {
    to_move <- rev(tail(x[[from]], qty))
    x[[from]] <- head(x[[from]], -qty)
    x[[to]] <- c(x[[to]], to_move)
    x
}

stacks <- data %>% 
    filter(str_detect(lines, "\\[")) %>% 
    arrange(-row_number()) %>% 
    separate(lines, into = paste0("c", 1:36), sep = "") %>% 
    pivot_longer(everything()) %>% 
    filter(str_detect(value, "[A-Z]")) %>% 
    pivot_wider(
        names_from = name, values_from = value, values_fn = list
    ) %>% 
    map(~ .x[[1]]) %>% 
    unname()

data %>% 
    filter(str_detect(lines, "move")) %>% 
    rowwise() %>% 
    transmute(
        qty = extract_next_number(lines, ""),
        from = extract_next_number(lines, "from"),
        to = extract_next_number(lines, "to"),
    ) %>% 
    group_split() %>% 
    walk(function(x) {
        qty <- x$qty[[1]]
        from <- x$from[[1]]
        to <- x$to[[1]]
        stacks <<- make_move(stacks, qty, from, to)
    })

stacks %>% map(last) %>% paste(collapse = "")
[1] "PTWLTDSJV"

Part 2: After the rearrangement procedure completes, what crate ends up on top of each stack?

Moving a single crate from stack 2 to stack 1 behaves the same as before:

[D]        
[N] [C]    
[Z] [M] [P]
 1   2   3 

However, the action of moving three crates from stack 1 to stack 3 means that those three moved crates stay in the same order, resulting in this new configuration:

        [D]
        [N]
    [C] [Z]
    [M] [P]
 1   2   3

I create a helper function and I test the previous example:

stacks2 <- list(
    c("Z","N", "D"),
    c("M","C"),
    c("P")
)

make_move_ordered <- function(x, qty, from, to) {
    to_move <- tail(x[[from]], qty)
    x[[from]] <- head(x[[from]], -qty)
    x[[to]] <- c(x[[to]], to_move)
    x
}

stacks2
[[1]]
[1] "Z" "N" "D"

[[2]]
[1] "M" "C"

[[3]]
[1] "P"
stacks2 %>% make_move_ordered(3, 1, 3)
[[1]]
character(0)

[[2]]
[1] "M" "C"

[[3]]
[1] "P" "Z" "N" "D"

Here the full code:

library(tidyverse)

data <- 
    read_csv(
        here::here("2022/05_input"),
        col_names = c("lines"),
        show_col_types = FALSE,
        skip_empty_rows = FALSE
    )

extract_next_number <- function(x, pattern) {
    x %>%
        substring(str_locate(x, pattern)[[1]]) %>% 
        str_extract("[0-9]+") %>% 
        as.numeric()
}

make_move_ordered <- function(x, qty, from, to) {
    to_move <- tail(x[[from]], qty)
    x[[from]] <- head(x[[from]], -qty)
    x[[to]] <- c(x[[to]], to_move)
    x
}

stacks <- data %>% 
    filter(str_detect(lines, "\\[")) %>% 
    arrange(-row_number()) %>% 
    separate(lines, into = paste0("c", 1:36), sep = "") %>% 
    pivot_longer(everything()) %>% 
    filter(str_detect(value, "[A-Z]")) %>% 
    pivot_wider(
        names_from = name, values_from = value, values_fn = list
    ) %>% 
    map(~ .x[[1]]) %>% 
    unname()

data %>% 
    filter(str_detect(lines, "move")) %>% 
    rowwise() %>% 
    transmute(
        qty = extract_next_number(lines, ""),
        from = extract_next_number(lines, "from"),
        to = extract_next_number(lines, "to"),
    ) %>% 
    group_split() %>% 
    walk(function(x) {
        qty <- x$qty[[1]]
        from <- x$from[[1]]
        to <- x$to[[1]]
        stacks <<- make_move_ordered(stacks, qty, from, to)
    })

stacks %>% map(last) %>% paste(collapse = "")
[1] "WZMFVGGZP"