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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
@@ -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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+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 (1 L, 9 L), .f = ~ "|" ) |>
+ str_c (collapse = "" ) |>
+ str_c (name, sep = " " )
+ }) |>
+ modify_at (.at = 1 L, .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 ()
+
+
+
+
+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 )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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
+
+
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