diff --git a/2022/R/day17.qmd b/2022/R/day17.qmd index 416f18d..7a9fbbc 100644 --- a/2022/R/day17.qmd +++ b/2022/R/day17.qmd @@ -14,11 +14,282 @@ author: library(tidyverse) # Read input from file -input <- read_lines("../input/day17.txt", skip_empty_rows = TRUE) +input <- read_lines("../input/day17.txt", skip_empty_rows = TRUE) |> + str_split_1("") ``` +## Part 1 + +Representing obstacles as 1s and empty space as 0s, represent the shapes of the falling blocks, the floor, and the walls as bitwise integers: + +```{r} + +block1 <- strtoi(c("000111100" ), base = 2) +block2 <- strtoi(c("000010000","000111000","000010000" ), base = 2) +block3 <- strtoi(c("000111000","000001000","000001000" ), base = 2) +block4 <- strtoi(c("000100000","000100000","000100000","000100000"), base = 2) +block5 <- strtoi(c("000110000","000110000" ), base = 2) + +walls <- strtoi("100000001", base = 2) +floor <- strtoi("111111111", base = 2) + +blocks <- list(block1, block2, block3, block4, block5) + +``` + +Define functions that give properties of the tower: + +```{r} + +# Print tower to terminal (for debugging) +print_tower <- function(tower) { + tower |> + imap_chr(\(row, name) { + row |> + intToBits() |> + rev() |> + tail(9) |> + as.integer() |> + case_match(0 ~ "·", 1 ~ "#") |> + modify_at(.at = c(1L, 9L), .f = ~ "|") |> + str_c(collapse = "") |> + str_c(name, sep = " ") + }) |> + modify_at(.at = 1L, .f = ~ if_else(.x == "|#######| 0", "+-------+ 0", .x)) |> + rev() |> + cat(sep = "\n") +} + +tower_height <- function(tower) { + idx <- max(which(tower != walls)) + tower[idx] |> + names() |> + as.double() +} + +tower_base <- function(tower) { + idx <- max(which(accumulate(tower, bitwOr, .dir = "backward") == floor)) + tower[idx] |> + names() |> + as.double() +} + +trim_tower <- function(tower) { + base <- tower_base(tower) + top <- tower_height(tower) + tower[as.character(base:top)] +} + +``` + +Define functions that move blocks and check if the move is valid: + +```{r} + +shift_block <- function(block, dir) { + f <- switch(dir, + "<" = bitwShiftL, + ">" = bitwShiftR + ) + f(block, 1) +} + +is_collision <- function(block, tower_slice) { + any(bitwAnd(block, tower_slice) > 0) +} + +# Try to move the block L/R if the move is valid, or return the old one if not +try_shift_block <- function(block, dir, tower_slice) { + new <- shift_block(block, dir) + if (is_collision(new, tower_slice)) + block + else + new +} + +``` + +Define a function to drop blocks onto a tower: + +```{r} + +drop_blocks <- function(jets, n_blocks) { + + tower <- floor + names(tower) <- 1:length(tower) - 1 + + n_jets <- length(jets) + time <- 0 + + # Cycle through the list of blocks and drop them in order + for (i in 1:n_blocks) { + + block_idx <- (i - 1) %% length(blocks) + 1 + block <- blocks[[block_idx]] + + # Initialize the vertical location of the block + block_loc <- 1:length(block) + 3 + tower_height(tower) + + # Add empty wall space to the top of the tower + add_walls <- rep(walls, length(block) + 3) |> + set_names(c(min(block_loc) - 3:1, block_loc)) + tower <- c(tower, add_walls) + + # Drop block until it comes to rest + repeat { + jet_idx <- time %% n_jets + 1 + + # Apply jet blast & increment time + block <- try_shift_block(block, jets[jet_idx], tower[as.character(block_loc)]) + time <- time + 1 + + # Check if block has come to rest; if so, add block to tower + if (is_collision(block, tower[as.character(block_loc - 1)])) { + tower[as.character(block_loc)] <- bitwOr(tower[as.character(block_loc)], block) + tower <- trim_tower(tower) + break + + } + # Otherwise drop block one unit and repeat the block jet seq + else { + block_loc <- block_loc - 1 + } + } + } + + tower +} + +``` + +Run on puzzle input: + +```{r} + +input |> + drop_blocks(2022) |> + tower_height() + +``` + +## Part 2 + +Modify the drop_blocks function to loop until a cycle is found and return cycle info: + +```{r} + +find_cycle <- function(jets) { + + tower <- floor + names(tower) <- 1:length(tower) - 1 + + n_jets <- length(jets) + time <- 0 + states <- tibble( + n_blocks = numeric(0), + tower_idx = list(), + tower_val = list(), + block_idx = numeric(0), + jet_idx = numeric(0) + ) + + i <- 1 + # Cycle through the list of blocks and drop them in order + repeat { + + block_idx <- (i - 1) %% length(blocks) + 1 + block <- blocks[[block_idx]] + + # Initialize the vertical location of the block + block_loc <- 1:length(block) + 3 + tower_height(tower) + + # Add empty wall space to the top of the tower + add_walls <- rep(walls, length(block) + 3) |> + set_names(c(min(block_loc) - 3:1, block_loc)) + tower <- c(tower, add_walls) + + # Drop block until it comes to rest + repeat { + jet_idx <- time %% n_jets + 1 + + # Apply jet blast & increment time + block <- try_shift_block(block, jets[jet_idx], tower[as.character(block_loc)]) + time <- time + 1 + + # Check if block has come to rest; if so, add block to tower + if (is_collision(block, tower[as.character(block_loc - 1)])) { + tower[as.character(block_loc)] <- bitwOr(tower[as.character(block_loc)], block) + tower <- trim_tower(tower) + + # Add block and jet index to the states list + states <- states |> + add_row( + n_blocks = i, + tower_idx = list(names(tower)), + tower_val = list(unname(tower)), + block_idx = block_idx, + jet_idx = jet_idx + ) + # print(tower) + break + + } + # Otherwise drop block one unit and repeat the block jet seq + else { + block_loc <- block_loc - 1 + } + } + + i <- i + 1 + + # After each block is dropped, check if a cycle has been found and return it + dupes <- states |> + filter(n_distinct(tower_val) != n(), .by = c(block_idx, jet_idx)) + + if (nrow(dupes) > 0) { + + cycle_length <- dupes |> + pull(n_blocks) |> + reduce(`-`) |> + abs() + + cycle_start <- dupes |> + pull(n_blocks) |> + min() + + cycle_height <- dupes |> + pull(tower_idx) |> + map(as.numeric) |> + reduce(`-`) |> + unique() |> + abs() + + return(list(length = cycle_length, start = cycle_start, height = cycle_height)) + return(dupes) + } + } +} + +``` + +Get the cycle of the puzzle input: + +```{r} + +cycle <- find_cycle(input) + +``` + +Using the cycle info from the output, compute the majority of the height using the cycle, then and add the height of the remaineder: + ```{r} +n_cycles <- floor((1000000000000 - cycle$start) / cycle$length) +n_blocks <- (1000000000000 - cycle$start) %% cycle$length + cycle$start + +((n_cycles * cycle$height) + tower_height(drop_blocks(input, n_blocks))) |> + format(scientific = FALSE) + ``` diff --git a/_freeze/2022/R/day17/execute-results/html.json b/_freeze/2022/R/day17/execute-results/html.json new file mode 100644 index 0000000..c2ebc53 --- /dev/null +++ b/_freeze/2022/R/day17/execute-results/html.json @@ -0,0 +1,15 @@ +{ + "hash": "af1897f0c7a96af5f4b5d699c1a86e00", + "result": { + "engine": "knitr", + "markdown": "---\ntitle: \"Day 17\"\ndate: 2022-12-17\nauthor:\n name: https://adventofcode.com/2022/day/17\n url: https://adventofcode.com/2022/day/17\n---\n\n\n\n\n## Setup\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Libraries\nlibrary(tidyverse)\n\n# Read input from file\ninput <- read_lines(\"../input/day17.txt\", skip_empty_rows = TRUE) |> \n str_split_1(\"\") \n```\n:::\n\n\n\n\n## Part 1\n\nRepresenting obstacles as 1s and empty space as 0s, represent the shapes of the falling blocks, the floor, and the walls as bitwise integers:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nblock1 <- strtoi(c(\"000111100\" ), base = 2)\nblock2 <- strtoi(c(\"000010000\",\"000111000\",\"000010000\" ), base = 2)\nblock3 <- strtoi(c(\"000111000\",\"000001000\",\"000001000\" ), base = 2)\nblock4 <- strtoi(c(\"000100000\",\"000100000\",\"000100000\",\"000100000\"), base = 2)\nblock5 <- strtoi(c(\"000110000\",\"000110000\" ), base = 2)\n\nwalls <- strtoi(\"100000001\", base = 2)\nfloor <- strtoi(\"111111111\", base = 2)\n\nblocks <- list(block1, block2, block3, block4, block5)\n```\n:::\n\n\n\n\nDefine functions that give properties of the tower:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Print tower to terminal (for debugging)\nprint_tower <- function(tower) {\n tower |>\n imap_chr(\\(row, name) {\n row |> \n intToBits() |> \n rev() |> \n tail(9) |> \n as.integer() |> \n case_match(0 ~ \"·\", 1 ~ \"#\") |> \n modify_at(.at = c(1L, 9L), .f = ~ \"|\") |> \n str_c(collapse = \"\") |> \n str_c(name, sep = \" \")\n }) |> \n modify_at(.at = 1L, .f = ~ if_else(.x == \"|#######| 0\", \"+-------+ 0\", .x)) |> \n rev() |> \n cat(sep = \"\\n\")\n}\n\ntower_height <- function(tower) {\n idx <- max(which(tower != walls))\n tower[idx] |>\n names() |> \n as.double()\n}\n\ntower_base <- function(tower) {\n idx <- max(which(accumulate(tower, bitwOr, .dir = \"backward\") == floor))\n tower[idx] |>\n names() |> \n as.double()\n}\n\ntrim_tower <- function(tower) {\n base <- tower_base(tower)\n top <- tower_height(tower)\n tower[as.character(base:top)]\n}\n```\n:::\n\n\n\n\nDefine functions that move blocks and check if the move is valid:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nshift_block <- function(block, dir) {\n f <- switch(dir, \n \"<\" = bitwShiftL, \n \">\" = bitwShiftR\n )\n f(block, 1)\n}\n\nis_collision <- function(block, tower_slice) {\n any(bitwAnd(block, tower_slice) > 0)\n}\n\n# Try to move the block L/R if the move is valid, or return the old one if not\ntry_shift_block <- function(block, dir, tower_slice) {\n new <- shift_block(block, dir)\n if (is_collision(new, tower_slice))\n block\n else\n new\n}\n```\n:::\n\n\n\n\nDefine a function to drop blocks onto a tower:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndrop_blocks <- function(jets, n_blocks) {\n \n tower <- floor\n names(tower) <- 1:length(tower) - 1\n \n n_jets <- length(jets)\n time <- 0\n \n # Cycle through the list of blocks and drop them in order\n for (i in 1:n_blocks) {\n \n block_idx <- (i - 1) %% length(blocks) + 1\n block <- blocks[[block_idx]]\n \n # Initialize the vertical location of the block\n block_loc <- 1:length(block) + 3 + tower_height(tower)\n \n # Add empty wall space to the top of the tower\n add_walls <- rep(walls, length(block) + 3) |> \n set_names(c(min(block_loc) - 3:1, block_loc))\n tower <- c(tower, add_walls)\n \n # Drop block until it comes to rest\n repeat {\n jet_idx <- time %% n_jets + 1\n \n # Apply jet blast & increment time\n block <- try_shift_block(block, jets[jet_idx], tower[as.character(block_loc)])\n time <- time + 1\n \n # Check if block has come to rest; if so, add block to tower\n if (is_collision(block, tower[as.character(block_loc - 1)])) {\n tower[as.character(block_loc)] <- bitwOr(tower[as.character(block_loc)], block)\n tower <- trim_tower(tower)\n break\n \n } \n # Otherwise drop block one unit and repeat the block jet seq\n else {\n block_loc <- block_loc - 1\n }\n }\n }\n \n tower\n}\n```\n:::\n\n\n\n\nRun on puzzle input:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\ninput |> \n drop_blocks(2022) |> \n tower_height()\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[1] 3133\n```\n\n\n:::\n:::\n\n\n\n\n## Part 2\n\nModify the drop_blocks function to loop until a cycle is found and return cycle info:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nfind_cycle <- function(jets) {\n \n tower <- floor\n names(tower) <- 1:length(tower) - 1\n \n n_jets <- length(jets)\n time <- 0\n states <- tibble(\n n_blocks = numeric(0),\n tower_idx = list(),\n tower_val = list(), \n block_idx = numeric(0), \n jet_idx = numeric(0)\n )\n \n i <- 1\n # Cycle through the list of blocks and drop them in order\n repeat {\n \n block_idx <- (i - 1) %% length(blocks) + 1\n block <- blocks[[block_idx]]\n \n # Initialize the vertical location of the block\n block_loc <- 1:length(block) + 3 + tower_height(tower)\n \n # Add empty wall space to the top of the tower\n add_walls <- rep(walls, length(block) + 3) |> \n set_names(c(min(block_loc) - 3:1, block_loc))\n tower <- c(tower, add_walls)\n \n # Drop block until it comes to rest\n repeat {\n jet_idx <- time %% n_jets + 1\n \n # Apply jet blast & increment time\n block <- try_shift_block(block, jets[jet_idx], tower[as.character(block_loc)])\n time <- time + 1\n \n # Check if block has come to rest; if so, add block to tower\n if (is_collision(block, tower[as.character(block_loc - 1)])) {\n tower[as.character(block_loc)] <- bitwOr(tower[as.character(block_loc)], block)\n tower <- trim_tower(tower)\n \n # Add block and jet index to the states list\n states <- states |> \n add_row(\n n_blocks = i,\n tower_idx = list(names(tower)),\n tower_val = list(unname(tower)),\n block_idx = block_idx,\n jet_idx = jet_idx\n )\n # print(tower)\n break\n \n } \n # Otherwise drop block one unit and repeat the block jet seq\n else {\n block_loc <- block_loc - 1\n }\n }\n \n i <- i + 1\n \n # After each block is dropped, check if a cycle has been found and return it\n dupes <- states |> \n filter(n_distinct(tower_val) != n(), .by = c(block_idx, jet_idx))\n \n if (nrow(dupes) > 0) {\n \n cycle_length <- dupes |>\n pull(n_blocks) |>\n reduce(`-`) |>\n abs()\n\n cycle_start <- dupes |>\n pull(n_blocks) |>\n min()\n \n cycle_height <- dupes |>\n pull(tower_idx) |> \n map(as.numeric) |> \n reduce(`-`) |> \n unique() |> \n abs()\n\n return(list(length = cycle_length, start = cycle_start, height = cycle_height))\n return(dupes)\n }\n }\n}\n```\n:::\n\n\n\n\nGet the cycle of the puzzle input:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncycle <- find_cycle(input)\n```\n:::\n\n\n\n\nUsing the cycle info from the output, compute the majority of the height using the cycle, then and add the height of the remaineder:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nn_cycles <- floor((1000000000000 - cycle$start) / cycle$length)\nn_blocks <- (1000000000000 - cycle$start) %% cycle$length + cycle$start\n\n((n_cycles * cycle$height) + tower_height(drop_blocks(input, n_blocks))) |> \n format(scientific = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[1] \"1547953216393\"\n```\n\n\n:::\n:::\n", + "supporting": [], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/2022/R/day01.html b/docs/2022/R/day01.html index 07bab29..d8edc66 100644 --- a/docs/2022/R/day01.html +++ b/docs/2022/R/day01.html @@ -400,6 +400,12 @@

Day 1

Day 16 + + diff --git a/docs/2022/R/day02.html b/docs/2022/R/day02.html index 189902e..b4a7f5c 100644 --- a/docs/2022/R/day02.html +++ b/docs/2022/R/day02.html @@ -400,6 +400,12 @@

Day 2

Day 16 + + diff --git a/docs/2022/R/day03.html b/docs/2022/R/day03.html index 818b259..2779f8a 100644 --- a/docs/2022/R/day03.html +++ b/docs/2022/R/day03.html @@ -400,6 +400,12 @@

Day 3

Day 16 + + diff --git a/docs/2022/R/day04.html b/docs/2022/R/day04.html index c433073..6406c0f 100644 --- a/docs/2022/R/day04.html +++ b/docs/2022/R/day04.html @@ -400,6 +400,12 @@

Day 4

Day 16 + + diff --git a/docs/2022/R/day05.html b/docs/2022/R/day05.html index 7da9bdb..7dff7d3 100644 --- a/docs/2022/R/day05.html +++ b/docs/2022/R/day05.html @@ -400,6 +400,12 @@

Day 5

Day 16 + + diff --git a/docs/2022/R/day06.html b/docs/2022/R/day06.html index 3bdd051..f32868e 100644 --- a/docs/2022/R/day06.html +++ b/docs/2022/R/day06.html @@ -400,6 +400,12 @@

Day 6

Day 16 + + diff --git a/docs/2022/R/day07.html b/docs/2022/R/day07.html index 566ae8c..ec671ae 100644 --- a/docs/2022/R/day07.html +++ b/docs/2022/R/day07.html @@ -400,6 +400,12 @@

Day 7

Day 16 + + diff --git a/docs/2022/R/day08.html b/docs/2022/R/day08.html index 9f52d3d..489672a 100644 --- a/docs/2022/R/day08.html +++ b/docs/2022/R/day08.html @@ -400,6 +400,12 @@

Day 8

Day 16 + + diff --git a/docs/2022/R/day09.html b/docs/2022/R/day09.html index e44b347..547e484 100644 --- a/docs/2022/R/day09.html +++ b/docs/2022/R/day09.html @@ -400,6 +400,12 @@

Day 9

Day 16 + + diff --git a/docs/2022/R/day10.html b/docs/2022/R/day10.html index 941b278..553c268 100644 --- a/docs/2022/R/day10.html +++ b/docs/2022/R/day10.html @@ -400,6 +400,12 @@

Day 10

Day 16 + + diff --git a/docs/2022/R/day11.html b/docs/2022/R/day11.html index 8158b37..b36f8c5 100644 --- a/docs/2022/R/day11.html +++ b/docs/2022/R/day11.html @@ -400,6 +400,12 @@

Day 11

Day 16 + + diff --git a/docs/2022/R/day12.html b/docs/2022/R/day12.html index 702783e..ee1cd18 100644 --- a/docs/2022/R/day12.html +++ b/docs/2022/R/day12.html @@ -400,6 +400,12 @@

Day 12

Day 16 + + diff --git a/docs/2022/R/day13.html b/docs/2022/R/day13.html index e1fe592..1302091 100644 --- a/docs/2022/R/day13.html +++ b/docs/2022/R/day13.html @@ -400,6 +400,12 @@

Day 13

Day 16 + + diff --git a/docs/2022/R/day14.html b/docs/2022/R/day14.html index d3abe19..f43050a 100644 --- a/docs/2022/R/day14.html +++ b/docs/2022/R/day14.html @@ -400,6 +400,12 @@

Day 14

Day 16 + + diff --git a/docs/2022/R/day15.html b/docs/2022/R/day15.html index a582dc1..b253263 100644 --- a/docs/2022/R/day15.html +++ b/docs/2022/R/day15.html @@ -400,6 +400,12 @@

Day 15

Day 16 + + diff --git a/docs/2022/R/day16.html b/docs/2022/R/day16.html index e8989fd..1f2840d 100644 --- a/docs/2022/R/day16.html +++ b/docs/2022/R/day16.html @@ -66,6 +66,7 @@ + @@ -399,6 +400,12 @@

Day 16

Day 16 + + @@ -1010,6 +1017,9 @@

Part 2

diff --git a/docs/2022/R/day17.html b/docs/2022/R/day17.html new file mode 100644 index 0000000..2e6b9fd --- /dev/null +++ b/docs/2022/R/day17.html @@ -0,0 +1,1158 @@ + + + + + + + + + + + +Day 17 – Advent of Code: Worked Solutions + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ +
+
+

Day 17

+

Advent of Code: Worked Solutions

+
+ + + +
+ +
+
About
+ +
+ +
+
Date
+
+

December 17, 2022

+
+
+ + +
+ + + +
+ + +
+

Setup

+
+
# Libraries
+library(tidyverse)
+
+# Read input from file
+input <- read_lines("../input/day17.txt", skip_empty_rows = TRUE) |> 
+  str_split_1("") 
+
+
+
+

Part 1

+

Representing obstacles as 1s and empty space as 0s, represent the shapes of the falling blocks, the floor, and the walls as bitwise integers:

+
+
block1 <- strtoi(c("000111100"                                    ), base = 2)
+block2 <- strtoi(c("000010000","000111000","000010000"            ), base = 2)
+block3 <- strtoi(c("000111000","000001000","000001000"            ), base = 2)
+block4 <- strtoi(c("000100000","000100000","000100000","000100000"), base = 2)
+block5 <- strtoi(c("000110000","000110000"                        ), base = 2)
+
+walls  <- strtoi("100000001", base = 2)
+floor  <- strtoi("111111111", base = 2)
+
+blocks <- list(block1, block2, block3, block4, block5)
+
+

Define functions that give properties of the tower:

+
+
# Print tower to terminal (for debugging)
+print_tower <- function(tower) {
+  tower |>
+  imap_chr(\(row, name) {
+    row |> 
+      intToBits() |> 
+      rev() |> 
+      tail(9) |> 
+      as.integer() |> 
+      case_match(0 ~ "·", 1 ~ "#") |> 
+      modify_at(.at = c(1L, 9L), .f = ~ "|") |> 
+      str_c(collapse = "") |> 
+      str_c(name, sep = " ")
+  }) |> 
+  modify_at(.at = 1L, .f = ~ if_else(.x == "|#######| 0", "+-------+ 0", .x)) |> 
+  rev() |> 
+  cat(sep = "\n")
+}
+
+tower_height <- function(tower) {
+  idx <- max(which(tower != walls))
+  tower[idx] |>
+    names() |> 
+    as.double()
+}
+
+tower_base <- function(tower) {
+  idx <- max(which(accumulate(tower, bitwOr, .dir = "backward") == floor))
+  tower[idx] |>
+    names() |> 
+    as.double()
+}
+
+trim_tower <- function(tower) {
+  base <- tower_base(tower)
+  top  <- tower_height(tower)
+  tower[as.character(base:top)]
+}
+
+

Define functions that move blocks and check if the move is valid:

+
+
shift_block <- function(block, dir) {
+  f <- switch(dir, 
+    "<" = bitwShiftL, 
+    ">" = bitwShiftR
+  )
+  f(block, 1)
+}
+
+is_collision <- function(block, tower_slice) {
+  any(bitwAnd(block, tower_slice) > 0)
+}
+
+# Try to move the block L/R if the move is valid, or return the old one if not
+try_shift_block <- function(block, dir, tower_slice) {
+  new <- shift_block(block, dir)
+  if (is_collision(new, tower_slice))
+    block
+  else
+    new
+}
+
+

Define a function to drop blocks onto a tower:

+
+
drop_blocks <- function(jets, n_blocks) {
+  
+  tower        <- floor
+  names(tower) <- 1:length(tower) - 1
+  
+  n_jets <- length(jets)
+  time   <- 0
+  
+  # Cycle through the list of blocks and drop them in order
+  for (i in 1:n_blocks) {
+    
+    block_idx <- (i - 1) %% length(blocks) + 1
+    block     <- blocks[[block_idx]]
+    
+    # Initialize the vertical location of the block
+    block_loc <- 1:length(block) + 3 + tower_height(tower)
+    
+    # Add empty wall space to the top of the tower
+    add_walls <- rep(walls, length(block) + 3) |> 
+      set_names(c(min(block_loc) - 3:1, block_loc))
+    tower <- c(tower, add_walls)
+    
+    # Drop block until it comes to rest
+    repeat {
+      jet_idx <- time %% n_jets + 1
+      
+      # Apply jet blast & increment time
+      block <- try_shift_block(block, jets[jet_idx], tower[as.character(block_loc)])
+      time <- time + 1
+      
+      # Check if block has come to rest; if so, add block to tower
+      if (is_collision(block, tower[as.character(block_loc - 1)])) {
+        tower[as.character(block_loc)] <- bitwOr(tower[as.character(block_loc)], block)
+        tower <- trim_tower(tower)
+        break
+        
+      } 
+      # Otherwise drop block one unit and repeat the block jet seq
+      else {
+        block_loc <- block_loc - 1
+      }
+    }
+  }
+  
+  tower
+}
+
+

Run on puzzle input:

+
+
input |> 
+  drop_blocks(2022) |> 
+  tower_height()
+
+
[1] 3133
+
+
+
+
+

Part 2

+

Modify the drop_blocks function to loop until a cycle is found and return cycle info:

+
+
find_cycle <- function(jets) {
+  
+  tower        <- floor
+  names(tower) <- 1:length(tower) - 1
+  
+  n_jets <- length(jets)
+  time   <- 0
+  states <- tibble(
+    n_blocks  = numeric(0),
+    tower_idx = list(),
+    tower_val = list(), 
+    block_idx = numeric(0), 
+    jet_idx   = numeric(0)
+  )
+  
+  i <- 1
+  # Cycle through the list of blocks and drop them in order
+  repeat {
+    
+    block_idx <- (i - 1) %% length(blocks) + 1
+    block     <- blocks[[block_idx]]
+    
+    # Initialize the vertical location of the block
+    block_loc <- 1:length(block) + 3 + tower_height(tower)
+    
+    # Add empty wall space to the top of the tower
+    add_walls <- rep(walls, length(block) + 3) |> 
+      set_names(c(min(block_loc) - 3:1, block_loc))
+    tower <- c(tower, add_walls)
+    
+    # Drop block until it comes to rest
+    repeat {
+      jet_idx <- time %% n_jets + 1
+      
+      # Apply jet blast & increment time
+      block <- try_shift_block(block, jets[jet_idx], tower[as.character(block_loc)])
+      time <- time + 1
+      
+      # Check if block has come to rest; if so, add block to tower
+      if (is_collision(block, tower[as.character(block_loc - 1)])) {
+        tower[as.character(block_loc)] <- bitwOr(tower[as.character(block_loc)], block)
+        tower <- trim_tower(tower)
+        
+        # Add block and jet index to the states list
+        states <- states |> 
+          add_row(
+            n_blocks  = i,
+            tower_idx = list(names(tower)),
+            tower_val = list(unname(tower)),
+            block_idx = block_idx,
+            jet_idx   = jet_idx
+          )
+        # print(tower)
+        break
+        
+      } 
+      # Otherwise drop block one unit and repeat the block jet seq
+      else {
+        block_loc <- block_loc - 1
+      }
+    }
+    
+    i <- i + 1
+    
+    # After each block is dropped, check if a cycle has been found and return it
+    dupes <- states |> 
+      filter(n_distinct(tower_val) != n(), .by = c(block_idx, jet_idx))
+    
+    if (nrow(dupes) > 0) {
+      
+      cycle_length <- dupes |>
+        pull(n_blocks) |>
+        reduce(`-`) |>
+        abs()
+
+      cycle_start <- dupes |>
+        pull(n_blocks) |>
+        min()
+      
+      cycle_height <- dupes |>
+        pull(tower_idx) |> 
+        map(as.numeric) |> 
+        reduce(`-`) |> 
+        unique() |> 
+        abs()
+
+      return(list(length = cycle_length, start = cycle_start, height = cycle_height))
+      return(dupes)
+    }
+  }
+}
+
+

Get the cycle of the puzzle input:

+
+
cycle <- find_cycle(input)
+
+

Using the cycle info from the output, compute the majority of the height using the cycle, then and add the height of the remaineder:

+
+
n_cycles <- floor((1000000000000 - cycle$start) / cycle$length)
+n_blocks <- (1000000000000 - cycle$start) %% cycle$length + cycle$start
+
+((n_cycles * cycle$height) + tower_height(drop_blocks(input, n_blocks))) |> 
+  format(scientific = FALSE)
+
+
[1] "1547953216393"
+
+
+ + +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/docs/2024/R/day01.html b/docs/2024/R/day01.html index 9f06740..0531442 100644 --- a/docs/2024/R/day01.html +++ b/docs/2024/R/day01.html @@ -399,6 +399,12 @@

Day 1

Day 16 + + diff --git a/docs/2024/R/day02.html b/docs/2024/R/day02.html index 6d11e44..86c9ef3 100644 --- a/docs/2024/R/day02.html +++ b/docs/2024/R/day02.html @@ -400,6 +400,12 @@

Day 2

Day 16 + + diff --git a/docs/2024/R/day03.html b/docs/2024/R/day03.html index 39b5dd3..6937371 100644 --- a/docs/2024/R/day03.html +++ b/docs/2024/R/day03.html @@ -400,6 +400,12 @@

Day 3

Day 16 + + diff --git a/docs/2024/R/day04.html b/docs/2024/R/day04.html index 871b4f2..6309633 100644 --- a/docs/2024/R/day04.html +++ b/docs/2024/R/day04.html @@ -400,6 +400,12 @@

Day 4

Day 16 + + diff --git a/docs/2024/R/day05.html b/docs/2024/R/day05.html index 7eecba0..e05ca4c 100644 --- a/docs/2024/R/day05.html +++ b/docs/2024/R/day05.html @@ -400,6 +400,12 @@

Day 5

Day 16 + + diff --git a/docs/2024/R/day06.html b/docs/2024/R/day06.html index 1d9d647..6e7a0f8 100644 --- a/docs/2024/R/day06.html +++ b/docs/2024/R/day06.html @@ -400,6 +400,12 @@

Day 6

Day 16 + + diff --git a/docs/2024/R/day07.html b/docs/2024/R/day07.html index 2130860..42b19ec 100644 --- a/docs/2024/R/day07.html +++ b/docs/2024/R/day07.html @@ -400,6 +400,12 @@

Day 7

Day 16 + + diff --git a/docs/2024/R/day08.html b/docs/2024/R/day08.html index 1927cec..b11f974 100644 --- a/docs/2024/R/day08.html +++ b/docs/2024/R/day08.html @@ -400,6 +400,12 @@

Day 8

Day 16 + + diff --git a/docs/2024/R/day09.html b/docs/2024/R/day09.html index 0121079..a03b39f 100644 --- a/docs/2024/R/day09.html +++ b/docs/2024/R/day09.html @@ -400,6 +400,12 @@

Day 9

Day 16 + + diff --git a/docs/2024/R/day10.html b/docs/2024/R/day10.html index 27ea0be..37dbcf8 100644 --- a/docs/2024/R/day10.html +++ b/docs/2024/R/day10.html @@ -400,6 +400,12 @@

Day 10

Day 16 + + diff --git a/docs/2024/R/day11.html b/docs/2024/R/day11.html index dd2bdc2..9c4a992 100644 --- a/docs/2024/R/day11.html +++ b/docs/2024/R/day11.html @@ -400,6 +400,12 @@

Day 11

Day 16 + + diff --git a/docs/2024/R/day12.html b/docs/2024/R/day12.html index 086b93d..25a86d9 100644 --- a/docs/2024/R/day12.html +++ b/docs/2024/R/day12.html @@ -400,6 +400,12 @@

Day 12

Day 16 + + diff --git a/docs/2024/R/day13.html b/docs/2024/R/day13.html index 9445ab3..ddd0ed5 100644 --- a/docs/2024/R/day13.html +++ b/docs/2024/R/day13.html @@ -400,6 +400,12 @@

Day 13

Day 16 + + diff --git a/docs/2024/R/day14.html b/docs/2024/R/day14.html index c8d25a3..2941bfe 100644 --- a/docs/2024/R/day14.html +++ b/docs/2024/R/day14.html @@ -400,6 +400,12 @@

Day 14

Day 16 + + diff --git a/docs/2024/R/day15.html b/docs/2024/R/day15.html index 1756c77..7262f64 100644 --- a/docs/2024/R/day15.html +++ b/docs/2024/R/day15.html @@ -400,6 +400,12 @@

Day 15

Day 16 + + diff --git a/docs/2024/R/day16.html b/docs/2024/R/day16.html index 9cb68a6..05f517b 100644 --- a/docs/2024/R/day16.html +++ b/docs/2024/R/day16.html @@ -400,6 +400,12 @@

Day 16

Day 16 + + diff --git a/docs/2024/R/day17.html b/docs/2024/R/day17.html index a835712..411a2cf 100644 --- a/docs/2024/R/day17.html +++ b/docs/2024/R/day17.html @@ -400,6 +400,12 @@

Day 17

Day 16 + + diff --git a/docs/2024/R/day18.html b/docs/2024/R/day18.html index 7f1c0db..359407c 100644 --- a/docs/2024/R/day18.html +++ b/docs/2024/R/day18.html @@ -400,6 +400,12 @@

Day 18

Day 16 + + diff --git a/docs/2024/R/day19.html b/docs/2024/R/day19.html index 6ebb212..6bbfeb7 100644 --- a/docs/2024/R/day19.html +++ b/docs/2024/R/day19.html @@ -400,6 +400,12 @@

Day 19

Day 16 + + diff --git a/docs/2024/R/day20.html b/docs/2024/R/day20.html index 8c8955e..df5b749 100644 --- a/docs/2024/R/day20.html +++ b/docs/2024/R/day20.html @@ -400,6 +400,12 @@

Day 20

Day 16 + + diff --git a/docs/2024/R/day21.html b/docs/2024/R/day21.html index 95c05a8..960f310 100644 --- a/docs/2024/R/day21.html +++ b/docs/2024/R/day21.html @@ -400,6 +400,12 @@

Day 21

Day 16 + + diff --git a/docs/2024/R/day22.html b/docs/2024/R/day22.html index 129dc97..632c8b6 100644 --- a/docs/2024/R/day22.html +++ b/docs/2024/R/day22.html @@ -400,6 +400,12 @@

Day 22

Day 16 + + diff --git a/docs/2024/R/day23.html b/docs/2024/R/day23.html index 3b66cd7..94e6ae5 100644 --- a/docs/2024/R/day23.html +++ b/docs/2024/R/day23.html @@ -400,6 +400,12 @@

Day 23

Day 16 + + diff --git a/docs/2024/R/day24.html b/docs/2024/R/day24.html index 2251966..5e73080 100644 --- a/docs/2024/R/day24.html +++ b/docs/2024/R/day24.html @@ -400,6 +400,12 @@

Day 24

Day 16 + + diff --git a/docs/2024/R/day25.html b/docs/2024/R/day25.html index 8ce27f5..0f5af2a 100644 --- a/docs/2024/R/day25.html +++ b/docs/2024/R/day25.html @@ -400,6 +400,12 @@

Day 25

Day 16 + + diff --git a/docs/index.html b/docs/index.html index 9602559..47e8bfa 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,7 +7,7 @@ - + Advent of Code: Worked Solutions