diff --git a/2023/R/day23.qmd b/2023/R/day23.qmd
new file mode 100644
index 0000000..86ff77f
--- /dev/null
+++ b/2023/R/day23.qmd
@@ -0,0 +1,188 @@
+---
+title: "Day 23"
+date: 2023-12-23
+author:
+ name: https://adventofcode.com/2023/day/23
+ url: https://adventofcode.com/2023/day/23
+---
+
+## Setup
+
+```{r setup}
+
+# Libraries
+library(tidyverse)
+library(igraph)
+
+# Read input from file
+input <- read_lines("../input/day23.txt", skip_empty_rows = FALSE)
+
+```
+
+## Part 1
+
+Convert text input to a directed graph:
+
+```{r}
+
+# Convert to a dataframe with IDs and coordinates per cell
+df <- input |>
+ str_split("") |>
+ enframe(name = "row") |>
+ unnest_longer(value, indices_to = "col") |>
+ mutate(id = row_number()) |>
+ filter(value != '#') |>
+ relocate(id, value, row, col)
+
+# Compute the list of directed edges between cells
+edges <- df |>
+ mutate(
+ row_n = row - 1,
+ row_s = row + 1,
+ col_w = col - 1,
+ col_e = col + 1
+ ) |>
+ left_join(df, join_by(x$row_n == y$row, col), suffix = c("", "_n")) |>
+ left_join(df, join_by(x$row_s == y$row, col), suffix = c("", "_s")) |>
+ left_join(df, join_by(x$col_w == y$col, row), suffix = c("", "_w")) |>
+ left_join(df, join_by(x$col_e == y$col, row), suffix = c("", "_e")) |>
+ select(-starts_with(c("row", "col", "value_"))) |>
+ pivot_longer(
+ starts_with("id_"),
+ names_to = "dir",
+ values_to = "neighbor",
+ names_prefix = "id_"
+ ) |>
+
+ # For slope tiles, remove any non-downhill neighbors
+ filter(
+ (value == "." & !is.na(neighbor)) |
+ (value == "^" & dir == "n") |
+ (value == "v" & dir == "s") |
+ (value == "<" & dir == "w") |
+ (value == ">" & dir == "e")
+ ) |>
+ pmap(\(id, neighbor, ...) c(id, neighbor)) |>
+ unlist()
+
+# Convert to a graph
+g <- make_graph(edges)
+
+```
+
+Find the longest possible path from the start point to the end point:
+
+```{r}
+
+source <- min(df$id)
+target <- max(df$id)
+
+max_hike <- function(g, from = source, to = target) {
+ all_simple_paths(g, from, to) |>
+ map_dbl(~ length(.x) - 1) |>
+ sort(decreasing = TRUE) |>
+ max()
+}
+
+max_hike(g)
+
+```
+
+## Part 2
+
+Convert to an undirected graph to remove the slope constraint:
+
+```{r}
+
+g <- as_undirected(g)
+V(g)$name <- V(g)
+
+```
+
+The graph is too large to simply run the hike length function again -- an overflow results.
+
+Instead, we notice that the input maze consists of relatively few intersections. Most of the maze input is simple corridors with no path decisions. We can reduce the graph complexity/size by trimming away our non-choice verftices and converting the length of those paths to an edge weight.
+
+```{r}
+
+v_zero_edges <- names(which(degree(g) == 0))
+v_two_edges <- names(which(degree(g) == 2))
+v_nontwo_edges <- names(which(degree(g) != 2))
+
+# Extract all corridor vertices
+g_corridors <- delete_vertices(g, v_nontwo_edges)
+corridors <- components(g_corridors)
+
+# Determine which edges to add to replace the corridors and their weight
+new_weights <- corridors$csize + 1
+new_edges <- corridors$membership |>
+ keep_at(names(which(degree(g_corridors) == 1))) |>
+ enframe(name = "vtx", value = "group") |>
+ mutate(vtx = map_chr(vtx, ~ setdiff(names(neighbors(g, .x)), v_two_edges))) |>
+ summarize(edge = list(vtx), .by = group) |>
+ arrange(group) |>
+ pull(edge)
+
+# Create a new graph without the corridor vertices, then add its new edges
+g_new <- reduce2(
+ .x = new_edges,
+ .y = new_weights,
+ .f = \(g, e, w) add_edges(g, e, weight = w),
+ .init = delete_vertices(g, c(v_zero_edges, v_two_edges))
+)
+
+```
+
+View a plot of the resulting simplified graph:
+
+```{r}
+#| fig-height: 9
+#| fig-width: 10
+
+vtx_labels <- g_new |>
+ V() |>
+ names() |>
+ case_match(
+ as.character(source) ~ "S",
+ as.character(target) ~ "E",
+ .default = ""
+ )
+
+plot(
+ g_new,
+ vertex.size = 8,
+ vertex.label = vtx_labels,
+ edge.label = E(g_new)$weight
+)
+
+```
+
+Compute all paths from the start to the end using our smaller graph:
+
+```{r}
+
+all_paths <- g_new |>
+ all_simple_paths(as.character(source), as.character(target))
+
+```
+
+Using the edge weights of our graph, compute the total length of each path and select the longest:
+
+```{r}
+
+all_paths |>
+ map(
+ ~ .x |>
+ as_ids() |>
+ rep(each = 2) |>
+ head(-1) |>
+ tail(-1) |>
+ get_edge_ids(graph = g_new)
+ ) |>
+ map(~ E(g_new)$weight[.x]) |>
+ map_dbl(sum) |>
+ max()
+
+```
+
+
diff --git a/2023/R/day24.qmd b/2023/R/day24.qmd
new file mode 100644
index 0000000..07407c1
--- /dev/null
+++ b/2023/R/day24.qmd
@@ -0,0 +1,183 @@
+---
+title: "Day 24"
+date: 2023-12-24
+author:
+ name: https://adventofcode.com/2023/day/24
+ url: https://adventofcode.com/2023/day/24
+---
+
+## Setup
+
+```{r setup}
+
+# Libraries
+library(tidyverse)
+library(unglue)
+
+# Read input from file
+input <- read_lines("../input/day24.txt", skip_empty_rows = FALSE)
+
+```
+
+## Part 1
+
+Convert text input to structured data:
+
+```{r}
+
+bound_min <- 200000000000000
+bound_max <- 400000000000000
+
+df <- input |>
+ unglue_data("{px}, {py}, {pz} @ {vx}, {vy}, {vz}", convert = TRUE) |>
+ mutate(id = row_number(), .before = everything())
+
+vecs_2d <- df |>
+ transmute(
+ id,
+ p = pmap(lst(px, py), ~ matrix(c(..1, ..2), ncol = 1)),
+ v = pmap(lst(vx, vy), ~ matrix(c(..1, ..2), ncol = 1))
+ )
+
+vecs_3d <- df |>
+ transmute(
+ id,
+ p = pmap(lst(px, py, pz), ~ matrix(c(..1, ..2, ..3), ncol = 1)),
+ v = pmap(lst(vx, vy, vz), ~ matrix(c(..1, ..2, ..3), ncol = 1))
+ )
+
+```
+
+The position $\vec a$ of a hailstone at any given time $t$ can be written in the format:
+
+$$\vec vt + \vec p$$
+
+The intersection of the paths of any two given hailstones is therefore the point $\vec a$ where:
+
+$$
+\vec a = \vec v_1t_1 + \vec p_1 = \vec v_2t_2 = \vec p_2
+$$
+
+This can be re-written as the system of equations:
+
+$$
+\begin{bmatrix}\vec v_1 &-\vec v_2\end{bmatrix}\begin{bmatrix}t_1\\t_2\end{bmatrix} = \vec p_2 - \vec p_1
+$$
+
+Solving this system of equations for each pair of hailstones will give us the values of $t_1$ and $t_2$ that can then be used to compute the coordinates of their intersection, $\vec a$.
+
+```{r}
+
+# Combine all hailstones' paths pairwise and solve the system of equations
+pairs <- inner_join(
+ vecs_2d,
+ vecs_2d,
+ join_by(x$id < y$id),
+ suffix = c("1", "2")
+) |>
+ mutate(
+ A = map2(v1, v2, ~ cbind(..1, -..2)),
+ b = map2(p1, p2, ~ ..2 - ..1),
+ det = map_dbl(A, det),
+ t = pmap(lst(A, b, det), \(A, b, det) if (det != 0) as.vector(solve(A, b)))
+ ) |>
+ unnest_wider(t, names_sep = "") |>
+
+ # Check if each path cross is within the bounding box and forward in time
+ mutate(
+ intersection = pmap(lst(t1, v1, p1), ~ ..1 * ..2 + ..3),
+ in_bounds = map_lgl(intersection, ~ all(between(.x, bound_min, bound_max))),
+ future_time = t1 >= 0 & t2 >= 0,
+ flag = replace_na(in_bounds & future_time, FALSE)
+ )
+
+# Count the number of future-crossing paths:
+pairs |>
+ pull(flag) |>
+ sum()
+
+```
+
+## Part 2
+
+Now our equation has changed. For each hailstone $i$, and for our initial position $\vec p_*$ and velocity $\vec v_*$, we have the following relationship, where $t_i$ is the nonzero collision time of our rock and the given hailstone:
+
+$$
+(\vec v_* - \vec v_i)t_i = \vec p_* - \vec p_i
+$$
+
+Since $t_i$ is a scalar for each $i$, then $\vec v_i - \vec v_*$ and $\vec p_i - \vec p_*$ are scalar multiples of each other. Thanks to a hint from Reddit user [u/evouga](https://www.reddit.com/r/adventofcode/comments/18pnycy/comment/kepu26z/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button), as these vectors are parallel, their cross product is zero, meaning that for all $i$:
+
+$$
+(\vec p_* - \vec p_i) \times (\vec v_* - \vec v_i) = 0
+$$
+
+Expanding this equation by the distributive property of the vector cross product, we get:
+
+$$
+(\vec p_* \times \vec v_*) - (\vec p_* \times \vec v_i) - (\vec p_i \times \vec v_*) + (\vec p_i \times \vec v_i) = 0
+$$
+
+Via [properties of the cross product](https://en.wikipedia.org/wiki/Cross_product#Conversion_to_matrix_multiplication), we can then represent this as:
+
+$$
+(\vec p_* \times \vec v_*) - [\vec v_i]_\times^\intercal \vec p_* - [\vec p_i]_\times \vec v_* + (\vec p_i \times \vec v_i) = 0
+$$
+
+where $[\vec a]_\times$ is defined as:
+
+$$
+[\vec a]_\times = \begin{bmatrix}0 & -a_3 & a_2 \\ a_3 & 0 & -a_1 \\ -a_2 & a_1 & 0\end{bmatrix}
+$$
+
+We can now (nearly) re-write this as a system of linear equations:
+
+$$
+A_i\vec x = \vec b_i + (\vec p_* \times \vec v_*)
+$$
+
+where
+
+$$
+A_i = \begin{bmatrix}[\vec v_i]_\times^\intercal & [\vec p_i]_\times\end{bmatrix}, \quad \vec x = \begin{bmatrix}\vec p_* \\ \vec v_*\end{bmatrix}, \quad b_i = (\vec p_i \times \vec v_i)
+$$
+
+Since this equation holds for all $i$, we can remove the needless term $(\vec p_* \times \vec v_*)$ and solve for $\vec x$ by subtracting two of these linear systems of equations from each other (using $i = 1,2$ as below, or any other two values of $i$ whose vectors from part 1 are not parallel):
+
+$$
+(A_1 - A_2)\vec x = \vec b_1 - \vec b_2
+$$
+
+Finally, since we've arrived at a system of 3 equations and 6 unknowns, we append $A$ and $\vec b$ with an additional pair of equations (using $i = 2,3$, for example) to solve for a final unique result:
+
+$$
+\begin{bmatrix}A_1 - A_2\\A_2 - A_3\end{bmatrix}\vec x = \begin{bmatrix}\vec b_1 - \vec b_2\\ \vec b_2 - \vec b_3\end{bmatrix}
+$$
+
+```{r}
+
+# Define a function to compute the skeq symmetric matrix [a]_x
+skewsym <- function(x) {
+ matrix(c(0, x[[3]], -x[[2]], -x[[3]], 0, x[[1]], x[[2]], -x[[1]], 0), ncol = 3)
+}
+
+# For the first three vectors in our list, compute their A and b values
+lineqs <- vecs_3d |>
+ slice_head(n = 3) |>
+ mutate(
+ A = map2(p, v, \(p, v) cbind(t(skewsym(v)), skewsym(p))),
+ b = map2(p, v, \(p, v) pracma::cross(p, v))
+ )
+
+# Combine the 3 linear equations into a single system & solve
+A <- rbind(lineqs$A[[1]] - lineqs$A[[2]], lineqs$A[[2]] - lineqs$A[[3]])
+b <- rbind(lineqs$b[[1]] - lineqs$b[[2]], lineqs$b[[2]] - lineqs$b[[3]])
+x <- solve(A, b)
+```
+
+Finally, add together the three px, py, and pz coordinates for the initial position:
+
+```{r}
+sum(x[1:3]) |>
+ format(scientific = FALSE)
+```
diff --git a/2023/R/day25.qmd b/2023/R/day25.qmd
new file mode 100644
index 0000000..707f366
--- /dev/null
+++ b/2023/R/day25.qmd
@@ -0,0 +1,83 @@
+---
+title: "Day 25"
+date: 2023-12-25
+author:
+ name: https://adventofcode.com/2023/day/25
+ url: https://adventofcode.com/2023/day/25
+---
+
+## Setup
+
+```{r setup}
+
+# Libraries
+library(tidyverse)
+library(unglue)
+library(igraph)
+
+# Read input from file
+input <- read_lines("../input/day25.txt", skip_empty_rows = FALSE)
+
+```
+
+## Part 1
+
+Convert text input to a graph:
+
+```{r}
+
+wires <- input |>
+ str_split(":? ") |>
+ unlist() |>
+ unique()
+
+edges <- input |>
+ unglue_data("{name}: {conn}") |>
+ mutate(conn = str_split(conn, " ")) |>
+ unnest_longer(conn) |>
+ mutate(across(c(name, conn), ~ match(.x, wires))) |>
+ pmap(\(name, conn) c(name, conn)) |>
+ unlist()
+
+g <- make_graph(edges, directed = FALSE)
+
+```
+
+Compute the betweenness of each edge and pull the three with the maximum values:
+
+```{r}
+
+scores <- edge_betweenness(g)
+idx <- scores |>
+ sort(decreasing = TRUE) |>
+ head(3) |>
+ match(scores)
+
+```
+
+Plot for visual confirmation:
+
+```{r}
+
+edge_colors <- E(g) |>
+ as.numeric() |>
+ case_match(idx ~ "blue", .default = "grey")
+
+plot(g, vertex.size = 4, vertex.label = NA, edge.color = edge_colors)
+
+```
+
+Remove the selected vertices from the graph, then calculate the product of the size of its two disconnected groups:
+
+```{r}
+
+g |>
+ delete_edges(idx) |>
+ components() |>
+ pluck("csize") |>
+ prod()
+
+```
+
+
+
diff --git a/2023/input/day23.txt b/2023/input/day23.txt
new file mode 100644
index 0000000..aef7c05
--- /dev/null
+++ b/2023/input/day23.txt
@@ -0,0 +1,141 @@
+#.###########################################################################################################################################
+#.#...#.......#...#.....#...#...#######...###...#...#.......#...#...#...#...#...#...#...###...###...###...............#.....#...#######...###
+#.#.#.#.#####.#.#.#.###.#.#.#.#.#######.#.###.#.#.#.#.#####.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.###.#.###.#############.#.###.#.#.#######.#.###
+#.#.#.#.#.....#.#.#...#.#.#...#...#.....#...#.#.#.#.#.....#...#.#.#.#.#.#.#.#.#...#...#.....#.#...#...#.............#.#...#...#.......#.#...#
+#.#.#.#.#.#####.#.###.#.#.#######.#.#######.#.#.#.#.#####.#####.#.#.#.#.#.#.#.###############.#.#####.#############.#.###.###########.#.###.#
+#...#...#.....#.#.###.#.#.#.......#.....#...#.#.#.#.#.>.>.#.....#.#.#.#.#.#.#...#.............#.#.....#...#.......#.#.....#...........#.#...#
+#############.#.#v###.#.#.#.###########.#.###.#.#.#.#.#v###.#####.#.#.#.#.#.###.#.#############.#.#####.#.#.#####.#.#######.###########.#.###
+#...###...###...#.>.#.#.#.#.#...###.....#.....#.#.#...#...#.#...#.#.#.#.#.#.###.#.#####...###...#...#...#.#...#...#.....#...#...###...#.#.###
+#.#.###.#.#######v#.#.#.#.#.#.#.###.###########.#.#######.#.#.#.#.#.#.#.#.#.###.#.#####.#.###.#####.#.###.###.#.#######.#.###.#.###.#.#.#.###
+#.#.#...#.#.....#.#.#.#.#.#...#...#.........#...#.###.....#.#.#.#.#.#.#.#.#.>.>.#.......#.#...#.....#...#.#...#.#.......#...#.#.....#.#.#.###
+#.#.#.###.#.###.#.#.#.#.#.#######.#########.#.###.###.#####.#.#.#.#.#.#.#.###v###########.#.###.#######.#.#.###.#.#########.#.#######.#.#.###
+#.#.#...#.#...#.#.#.#.#.#...#.....#...#...#.#...#...#.....#.#.#.#.#.#.#...###.#...........#...#.....#...#.#...#.#.........#.#.#.......#.#.###
+#.#.###.#.###.#.#.#.#.#.###.#.#####.#.#.#.#.###.###.#####.#.#.#.#.#.#.#######.#.#############.#####.#.###.###.#.#########.#.#.#.#######.#.###
+#.#.....#.#...#.#.#.#.#.#...#.....#.#...#.#...#.#...#.....#...#...#.#.#.......#.#.....#.....#.#.....#...#.###.#.#...#.....#...#.#...###.#.###
+#.#######.#.###.#.#.#.#.#.#######.#.#####.###.#.#.###.#############.#.#.#######.#.###.#.###.#.#.#######.#.###.#.#.#.#.#########.#.#.###.#.###
+#.#...###...###.#.#...#.#...#.....#.#...#...#.#.#...#...........###...#.......#.#.#...#...#.#.#.#...###.#.###.#.#.#.#.....#.....#.#.#...#...#
+#.#.#.#########.#.#####.###.#.#####.#.#.###.#.#.###.###########.#############.#.#.#.#####.#.#.#.#.#.###.#.###.#.#.#.#####.#.#####.#.#.#####.#
+#.#.#.........#...#.....#...#.#...#...#...#...#.....#####.......#...###.......#.#.#.#.....#.#.#.#.#.#...#.>.>.#.#.#.#.....#...#...#...###...#
+#.#.#########.#####.#####.###.#.#.#######.###############.#######.#.###.#######.#.#.#.#####.#.#.#.#.#.#####v###.#.#.#.#######.#.#########.###
+#...#.......#.#...#...#...###.#.#.>.>...#...#...#...###...###...#.#...#.......#.#.#...###...#.#.#.#.#...#...###...#...###.....#.###.......###
+#####.#####.#.#.#.###.#.#####.#.###v###.###.#.#.#.#.###.#####.#.#.###.#######.#.#.#######.###.#.#.#.###.#.###############.#####.###.#########
+#...#.....#...#.#.###...#####...#...###.....#.#.#.#.#...#...#.#...#...#.......#.#.#.....#.....#.#.#.....#...#...........#.#...#...#...#.....#
+#.#.#####.#####.#.###############.###########.#.#.#.#.###.#.#.#####.###.#######.#.#.###.#######.#.#########.#.#########.#.#.#.###.###.#.###.#
+#.#.......#...#.#.#...#...###...#.....#.......#.#.#...#...#...#.....###.......#...#...#.#.....#.#...#...###...#.........#...#.#...###...#...#
+#.#########.#.#.#.#.#.#.#.###.#.#####.#.#######.#.#####.#######.#############.#######.#.#.###.#.###.#.#.#######.#############.#.#########.###
+#.........#.#.#.#.#.#.#.#...#.#.......#.#.......#.......###.....#...#.........###...#.#.#.#...#.....#.#.#...###.............#...#...#...#...#
+#########.#.#.#.#.#.#.#.###.#.#########.#.#################.#####.#.#.###########.#.#.#.#.#.#########.#.#.#.###############.#####.#.#.#.###.#
+#.........#.#.#.#.#.#.#...#.#.......###.#.#...#...#...#...#.....#.#.#.......#...#.#...#.#.#...#.......#.#.#...#.............#...#.#...#.....#
+#.#########.#.#.#.#.#.###.#.#######v###.#.#.#.#.#.#.#.#.#.#####v#.#.#######.#.#.#.#####.#.###.#.#######.#.###.#.#############.#.#.###########
+#...........#.#.#...#.#...#...#...>.>.#.#...#.#.#...#.#.#...#.>.>.#.#...###.#.#.#.....#.#.#...#.......#.#...#.#...#...#...###.#.#...........#
+#############.#.#####.#.#####.#.###v#.#.#####.#.#####.#.###.#.#v###.#.#.###v#.#.#####.#.#.#.#########.#.###.#.###v#.#.#.#.###.#.###########.#
+#...#...#.....#.....#.#.#.....#.#...#.#.....#.#...###...#...#.#...#.#.#.#.>.>.#.#...#.#.#.#...#.......#...#.#.#.>.>.#...#...#.#...#.........#
+#.#.#.#.#.#########.#.#.#.#####.#.###.#####.#.###.#######.###.###.#.#.#.#.#v###.#.#.#.#.#.###.#.#########.#.#.#.#v#########.#.###.#.#########
+#.#...#.#.#####...#.#.#.#.#.....#...#...#...#.#...#.....#...#...#.#...#...#.###...#...#...#...#.......###...#...#.#...#...#.#.#...#...#...###
+#.#####.#.#####.#.#.#.#.#.#.#######.###.#.###.#.###.###.###.###.#.#########.###############.#########.###########.#.#.#.#.#.#.#.#####.#.#.###
+#.....#...###...#.#.#...#...#.....#...#.#.#...#.....#...###.....#.....#.....#...#...#...###...#.......#...#...###.#.#...#...#.#...###...#...#
+#####.#######.###.#.#########.###.###.#.#.#.#########.###############.#.#####.#.#.#.#.#.#####.#.#######.#.#.#.###.#.#########.###.#########.#
+#.....#...#...###...#...#.....###...#.#.#.#.#...#...#...#.............#...#...#...#...#.....#.#.....#...#...#...#.#.###...###...#.#...#.....#
+#.#####.#.#.#########.#.#.#########.#.#.#.#.#.#.#.#.###.#.###############.#.###############.#.#####.#.#########.#.#.###.#.#####.#.#.#.#.#####
+#.....#.#...#####.....#.#.........#...#.#.#.#.#...#.#...#...............#...#...............#.#.....#.#.....#...#.#.#...#.#...#.#.#.#.#...###
+#####.#.#########.#####.#########.#####.#.#.#.#####.#.#################.#####.###############.#.#####.#.###.#.###.#.#.###.#.#.#.#.#.#.###v###
+#...#.#.........#.#...#...........#...#...#.#.....#.#.#.................#.....#.....#.......#.#.....#...#...#.....#.#.###.#.#.#.#.#.#.#.>.###
+#.#.#v#########.#.#.#.#############.#.#####.#####.#.#.#.#################.#####.###.#.#####.#.#####.#####.#########.#.###.#.#.#.#.#.#.#.#v###
+#.#.#.>...#.....#...#...............#.....#.#...#.#...#.#...#...........#.#.....###...#.....#.......#...#.........#.#...#.#.#...#.#.#...#...#
+#.#.#v###.#.#############################.#.#.#.#.#####.#.#.#.#########.#.#.###########.#############.#.#########.#.###.#.#.#####.#.#######.#
+#.#.#...#.#.......#.......................#...#...#...#...#...#...#.....#.#.#...........#...#...###...#...........#.#...#.#.#.....#.#.......#
+#.#.###.#.#######.#.###############################.#.#########.#.#.#####.#.#.###########.#.#.#.###.###############.#.###.#.#.#####.#.#######
+#.#.....#.........#...#...#.........###...#...#...#.#.#.........#...#...#...#.#...........#.#.#...#.........#.....#...###.#.#.#.....#.#.....#
+#.###################.#.#.#.#######.###.#.#.#.#.#.#.#.#.#############.#.#####.#.###########.#.###.#########.#.###.#######.#.#.#.#####.#.###.#
+#...#...###.....#...#...#.#.#.......#...#...#.#.#.#.#.#.............#.#.....#...#...........#.#...#.........#...#.....###...#...#...#...#...#
+###.#.#.###.###.#.#.#####.#.#.#######.#######.#.#.#.#.#############.#.#####.#####.###########.#.###.###########.#####.###########.#.#####.###
+#...#.#...#...#.#.#.#.....#.#.....###.#.......#.#...#...#...#...###...#.....#...#.......#...#.#.###.......###...#.....#...#.....#.#...###...#
+#.###.###.###.#.#.#.#.#####.#####.###.#.#######.#######.#.#.#.#.#######.#####.#.#######.#.#.#.#.#########v###.###.#####.#.#.###.#.###.#####.#
+#.....###.....#.#.#.#.......#...#...#.#.....###.......#.#.#...#.#.......#####.#.........#.#.#.#...#.....>.>.#...#.#...#.#.#.#...#...#.###...#
+###############.#.#.#########.#.###.#.#####.#########.#.#.#####.#.###########.###########.#.#.###.#.#####v#.###.#.#.#.#.#.#.#.#####.#.###v###
+#...............#.#.#.......#.#.....#.#.....#...#...#.#.#.....#.#...........#...#...#...#.#.#.#...#.....#.#.....#.#.#.#.#.#.#...#...#...>.###
+#.###############.#.#.#####.#.#######.#.#####.#.#.#.#.#.#####.#.###########.###.#.#.#.#.#.#.#.#.#######.#.#######.#.#.#.#.#.###.#.#######v###
+#...#.....#...###.#.#.....#.#.#...###.#.#...#.#.#.#.#.#.#...#.#.###.........###...#...#.#.#...#...#.....#.....#...#.#...#.#...#.#.#.....#.###
+###.#.###.#.#.###.#.#####.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.###v###################.#.#######.#.#########.#.###.#####.###.#.#.#.###.#.###
+###...###.#.#.#...#.#.....#...#.#.#...#.#.#.#.#.#.#.#.#.#.#...#...>.>.........#...#.....#.....#...#...#.......#.....#.....#...#...#...#...###
+#########v#.#.#.###.#.#########.#.#.###.#.#.#.#.#.#.#.#.#.#########v#########.#.#.#.#########.#.#####.#.#############.#####.#########.#######
+#...#...#.>.#.#...#.#.........#.#.#.#...#.#.#.#.#.#.#.#.#.#.........###.......#.#.#.....#.....#.....#.#...#.........#...#...#.........#...###
+#.#.#.#.#v###.###.#.#########.#.#.#.#.###.#.#.#.#.#.#.#.#.#.###########.#######.#.#####.#.#########.#.###.#.#######.###.#.###.#########.#.###
+#.#...#...###.....#.#...#.....#.#...#...#.#.#.#.#.#...#...#...#.....#...#.....#.#.#.....#.......###.#.###...#...#...#...#...#.#...#.....#...#
+#.#################.#.#.#.#####.#######.#.#.#.#.#.###########.#.###.#.###.###.#.#.#.###########.###.#.#######.#.#.###.#####.#.#.#.#.#######.#
+#.............#.....#.#.#.....#.....###...#.#.#.#.###...#...#...#...#...#.#...#.#.#.#.....#...#...#.#.#.......#...###...#...#...#...#.......#
+#############.#.#####.#.#####v#####.#######.#.#.#.###.#.#.#.#####.#####.#.#.###.#.#v#.###.#.#.###.#.#.#.###############.#.###########.#######
+#.............#.#...#.#...#.>.>.....#.....#.#.#.#.#...#...#.......#####.#.#.....#.>.>.###.#.#.....#.#.#.......#.....###.#...#.......#.......#
+#.#############.#.#.#.###.#.#v#######.###.#.#.#.#.#.###################.#.#########v#####.#.#######.#.#######.#.###.###.###.#.#####.#######.#
+#.........#...#...#.#.###.#.#.........#...#...#...#.......#.........#...#...#.......#...#...#...###.#.#.....#...#...#...#...#.....#.........#
+#########.#.#.#####.#.###.#.###########.#################.#.#######.#.#####.#.#######.#.#####.#.###.#.#.###.#####.###.###.#######.###########
+#.........#.#.#...#...###...#.........#.#...#...#.......#...#...#...#.#.....#.......#.#.......#...#...#...#.#...#...#.....#...###...........#
+#.#########.#.#.#.###########.#######.#.#.#.#.#.#.#####.#####.#.#.###.#.###########.#.###########.#######.#.#.#.###.#######.#.#############.#
+#...#...#...#.#.#.#...#.......#...###...#.#.#.#.#.....#...#...#...###...#...###...#.#.#...........#...#...#...#.....#...###.#.#...#.......#.#
+###.#.#.#.###.#.#v#.#.#.#######.#.#######.#.#.#.#####.###.#.#############.#.###.#.#.#.#.###########.#.#.#############.#.###.#.#.#.#.#####.#.#
+#...#.#.#.#...#.#.>.#.#.....#...#...#...#.#.#.#.#...#.#...#.......#...#...#.#...#.#...#.....#.....#.#...#.....###...#.#.#...#.#.#.#...###...#
+#.###.#.#.#.###.#v###.#####.#.#####.#.#.#.#.#.#.#.#.#.#.#########.#.#.#.###.#.###.#########.#.###.#.#####.###.###.#.#.#.#.###.#.#.###v#######
+#.....#.#.#...#.#.#...#...#...###...#.#.#.#.#.#.#.#...#.#.......#.#.#.#...#.#...#.###...#...#.#...#...#...###...#.#...#.#...#.#.#...>.###...#
+#######.#.###.#.#.#.###.#.#######.###.#.#.#.#.#.#.#####.#.#####.#.#.#.###.#.###.#.###.#.#v###.#.#####.#.#######.#.#####.###.#.#.#####v###.#.#
+#...###...###...#.#...#.#...#...#.###.#.#.#.#.#.#.....#.#.#.....#.#.#.#...#...#.#.#...#.>.>.#.#.....#...#.......#.#.....#...#.#...#...###.#.#
+#.#.#############.###.#.###.#.#.#v###.#.#.#.#.#.#####.#.#.#.#####v#.#.#.#####.#.#.#.#####v#.#.#####.#####.#######.#.#####.###.###.#.#####.#.#
+#.#.#...#.....#...###.#.#...#.#.>.>.#.#.#.#.#.#...#...#.#.#.#...>.>.#.#.....#.#.#.#.#.....#...#.....#...#.....#...#.....#...#.#...#.......#.#
+#.#.#.#.#.###.#.#####.#.#.###.###v#.#.#.#.#.#.###.#.###.#.#.#.###v###.#####.#.#.#.#.#.#########.#####.#.#####.#.#######.###.#.#.###########.#
+#.#.#.#.#...#.#...#...#.#...#.#...#...#.#.#.#.###...#...#.#.#.#...###...#...#.#.#.#.#.......#...###...#...###.#.......#.#...#.#.#.....#...#.#
+#.#.#.#.###.#.###.#.###.###.#.#.#######.#.#.#.#######.###.#.#.#.#######.#.###.#.#.#.#######.#.#####.#####.###.#######.#.#.###.#.#.###.#.#.#.#
+#.#...#.#...#.#...#...#...#...#.......#.#.#.#...#.....#...#...#.......#.#...#...#...#...#...#.......#.....#...#...#...#.#.###...#...#...#...#
+#.#####.#.###.#.#####.###.###########.#.#.#.###.#.#####.#############.#.###.#########.#.#.###########.#####.###.#.#.###.#.#########.#########
+#.#...#...###...#.....#...#...........#...#.....#...#...#...#...#...#.#.#...#...#...#.#.#...#.........#...#...#.#.#...#...#####...#.........#
+#.#.#.###########.#####.###.#######################.#.###.#.#.#.#.#.#.#.#.###.#.#.#.#.#.###.#.#########.#.###v#.#.###.#########.#.#########.#
+#...#.........###.....#...#.......###...#.........#...#...#...#...#.#.#...#...#...#...#.....#.....#...#.#.#.>.>.#...#.#.........#...........#
+#############.#######.###.#######.###.#.#.#######.#####.###########.#.#####.#####################.#.#.#.#.#.#v#####.#.#.#####################
+#.............#...###.....#.....#.....#...#...#...#.....#.......#...#.#...#.................#.....#.#...#...#...###...#.#...#...#.......#...#
+#.#############.#.#########.###.###########.#.#.###.#####.#####.#.###.#.#.#################.#.#####.###########.#######.#.#.#.#.#.#####.#.#.#
+#.#.....#...###.#.....#...#...#...........#.#...###.......#...#.#...#.#.#.#.........#...#...#...#...#.......#...#...###...#...#...#...#...#.#
+#.#.###.#.#.###.#####.#.#.###.###########.#.###############.#.#.###.#.#.#.#.#######.#.#.#.#####.#.###.#####.#.###.#.###############.#.#####.#
+#...###...#...#...#...#.#.###.........#...#.......#.........#.#.#...#.#.#.#.......#.#.#.#.#...#...###.....#.#.....#...#.............#.....#.#
+#############.###.#.###.#.###########.#.#########.#.#########.#.#.###.#.#.#######.#.#.#.#.#.#.###########.#.#########.#.#################.#.#
+#...###.......#...#...#.#.#...........#.....#.....#.........#...#.....#.#.........#.#.#.#.#.#.............#...#.......#.................#.#.#
+#.#.###v#######.#####.#.#.#.###############.#.#############.###########.###########.#.#.#.#.#################.#.#######################.#.#.#
+#.#...#.>.#.....#.....#.#.#...............#.#...#...#######.....#...###...........#.#.#.#.#.#.......#...#####...###.....#...#...###.....#.#.#
+#.###.#v#.#.#####.#####.#.###############.#.###.#.#.###########.#.#.#############.#.#.#.#.#.#.#####.#.#.###########.###.#.#.#.#.###.#####.#.#
+#...#...#...#.....#...#.#...#.............#.#...#.#.###.........#.#.#...###.......#...#...#...###...#.#...#...#...#...#.#.#.#.#...#.....#...#
+###.#########.#####.#.#.###.#.#############.#.###.#.###.#########.#.#.#.###.#####################.###.###.#.#.#.#.###.#.#.#.#.###.#####.#####
+#...#.......#.....#.#.#.#...#.....#...#...#...###.#...#.......#...#...#...#.........#...#...#...#.....#...#.#.#.#.###.#.#.#.#.#...#.....#...#
+#.###.#####.#####.#.#.#.#.#######.#.#.#.#.#######.###.#######.#.#########.#########.#.#.#.#.#.#.#######.###.#.#.#.###.#.#.#.#.#.###v#####.#.#
+#.....#.....#...#...#...#...#.....#.#...#.#.......#...#.......#...#.......#.........#.#.#.#.#.#.#...###.###.#.#.#.#...#.#.#.#.#.#.>.###...#.#
+#######.#####.#.###########.#.#####.#####.#.#######.###.#########.#.#######.#########.#.#.#.#.#.#.#.###v###.#.#.#.#.###.#.#.#.#.#.#v###.###.#
+#.......#.....#.#...#.......#.......#.....#.......#.###.....#...#.#...#...#.....###...#.#.#.#.#.#.#.#.>.>...#.#.#...###.#.#.#.#...#...#.#...#
+#.#######.#####.#.#.#.###############.###########.#.#######.#.#.#.###.#.#.#####.###.###.#.#.#.#.#.#.#.#v#####.#.#######.#.#.#.#######.#.#.###
+#.......#.#.....#.#.#.....#.....#.....#...#...#...#...#...#.#.#.#.#...#.#.#...#.#...###.#.#...#.#.#...#.....#.#.......#.#.#.#...#.....#.#...#
+#######.#.#.#####.#.#####.#.###.#.#####.#.#.#.#.#####.#.#.#.#.#.#.#.###.#.#.#.#v#.#####.#.#####.#.#########.#.#######.#.#.#.###.#.#####.###.#
+#.......#.#...#...#...#...#...#.#.#...#.#.#.#.#...#...#.#.#.#.#.#.#...#.#.#.#.>.>.###...#.....#.#.###.......#.#.......#.#.#.#...#.......#...#
+#.#######.###.#.#####.#.#####.#.#v#.#.#.#.#.#.###.#.###.#.#v#.#.#.###.#.#.#.###v#####.#######.#.#.###.#######.#.#######.#.#.#.###########.###
+#...#...#...#.#.#.....#.#...#.#.>.>.#.#.#...#.#...#...#.#.>.>.#.#.#...#.#...###.....#...#...#.#.#.#...#.....#.#.....###...#.#...#.........###
+###.#.#.###.#.#.#.#####.#.#.#.###v###.#.#####.#.#####.#.###v###.#.#.###.###########.###.#.#.#.#.#.#.###.###.#.#####.#######.###.#.###########
+###.#.#.#...#...#.....#...#...###.#...#.....#...#.....#.###...#...#.....#...#...#...#...#.#.#.#.#.#...#.#...#...#...#...###.....#...........#
+###.#.#.#.###########.###########.#.#######.#####.#####.#####.###########.#.#.#.#.###.###.#.#.#.#.###.#.#.#####.#.###.#.###################.#
+#...#.#.#.#...........###...#.....#...#...#.....#.#.....#####.......#.....#...#.#...#.#...#...#...###...#.....#.#.###.#.#...#...#...........#
+#.###.#.#.#.#############.#.#.#######.#.#.#####.#.#.###############.#.#########.###.#.#.#####################.#.#.###.#.#.#.#.#.#.###########
+#...#.#.#.#.#...........#.#.#.#.....#.#.#.#.....#...#...............#...#...###.....#.#...#.................#.#.#.#...#...#.#.#.#.........###
+###.#.#.#.#.#.#########.#.#.#.#.###.#.#.#.#.#########.#################.#.#.#########.###.#.###############.#.#.#.#.#######.#.#.#########.###
+###.#.#.#.#.#.#.......#...#.#...#...#.#.#.#...#...#...#...#.......#...#...#.........#.....#...............#...#...#...#.....#.#.#...#...#...#
+###.#.#.#.#.#.#.#####.#####.#####.###.#.#.###.#.#.#.###.#.#.#####.#.#.#############.#####################.###########.#.#####.#.#.#.#v#.###.#
+###.#.#.#.#...#.....#.#...#.#...#.###...#.....#.#.#...#.#...#.....#.#.#.............###...#...#.....#...#.#.......#...#...#...#.#.#.>.#.....#
+###.#.#.#.#########.#.#.#.#.#.#.#.#############.#.###.#.#####.#####.#.#.###############.#.#.#.#.###.#.#.#.#.#####.#.#####.#.###.#.###v#######
+###...#...#.....#...#...#...#.#.#...........###.#.###...#.....###...#.#.......#.......#.#.#.#.#...#...#.#.#.....#...###...#...#...#...#...###
+###########.###.#.###########.#.###########.###.#.#######.#######.###.#######.#.#####.#.#.#.#.###.#####.#.#####.#######.#####.#####.###.#.###
+#.......###...#...#...###.....#.............#...#.......#.......#.#...#...#...#.#.....#.#.#.#.###.....#...#...#.......#.......#...#.....#...#
+#.#####.#####.#####.#.###.###################.#########.#######.#.#.###.#.#.###.#.#####.#.#.#.#######.#####.#.#######.#########.#.#########.#
+#.....#.......#...#.#...#.........#...###...#...#.......#...#...#.#...#.#...#...#.#...#.#.#.#.#...#...#...#.#.###...#...###.....#...........#
+#####.#########.#.#.###.#########v#.#.###.#.###.#.#######.#.#.###.###.#.#####.###.#.#.#.#.#.#.#.#.#.###.#.#.#.###.#.###.###.#################
+#.....#.......#.#.#.###...#...#.>.>.#...#.#.#...#...#.....#...###...#.#.....#.#...#.#.#.#.#.#.#.#.#...#.#.#.#.#...#.....#...#.....#.....#####
+#.#####.#####.#.#.#.#####.#.#.#.#######.#.#.#.#####.#.#############.#.#####v#.#.###.#.#.#.#.#.#.#.###v#.#.#.#.#.#########.###.###.#.###.#####
+#.....#.#.....#.#.#.#####.#.#...#.......#.#.#...#...#.........###...#.#...>.>.#.#...#.#.#...#.#.#...>.>.#.#.#.#.........#...#.#...#.###...###
+#####.#.#.#####.#.#.#####.#.#####.#######.#.###.#.###########v###.###.#.#######.#.###.#.#####.#.#########.#.#.#########.###.#.#.###.#####.###
+#####...#.....#.#...#.....#.....#.......#.#...#.#...#...#...>.>.#.###.#.....###.#.###.#.###...#.......#...#.#.#.......#.#...#.#.....#...#...#
+#############.#.#####.#########.#######.#.###.#.###.#.#.#.#####.#.###.#####.###.#.###.#.###.#########.#.###.#.#.#####.#.#.###.#######.#.###.#
+#.............#...#...#...#.....#.......#.#...#...#.#.#.#.....#.#.#...#.....#...#...#.#...#.....#.....#...#.#.#.....#.#.#...#.#.......#.....#
+#.###############.#.###.#.#.#####.#######.#.#####.#.#.#.#####.#.#.#.###.#####.#####.#.###.#####.#.#######.#.#.#####.#.#.###.#.#.#############
+#.................#.....#...#####.........#.......#...#.......#...#.....#####.......#.....#####...#######...#.......#...###...#.............#
+###########################################################################################################################################.#
diff --git a/2023/input/day24.txt b/2023/input/day24.txt
new file mode 100644
index 0000000..f8bdad8
--- /dev/null
+++ b/2023/input/day24.txt
@@ -0,0 +1,300 @@
+233210433951170, 272655040388795, 179982504986147 @ 39, -98, 166
+385274025881243, 351578921558552, 375160114124378 @ -71, -36, -9
+298962016918939, 322446494312107, 293073189215975 @ 36, 8, 96
+201717428991179, 262965089923292, 196011482381270 @ 92, -490, -114
+247277712435905, 218345997267326, 196010243400590 @ -165, -58, -21
+352675244632049, 554364732018242, 152625975899360 @ -14, -223, 247
+324422391745634, 227138986518940, 108773241649847 @ -47, 91, 312
+313067186829719, 462648141629189, 246008354182145 @ -32, -268, 104
+248189680078635, 407471031162962, 290189220302863 @ 84, -111, 82
+199505021061112, 177980659229372, 175893468794335 @ 75, 219, -136
+323521328529479, 153391146336101, 520509666624452 @ 8, 190, -153
+360051136858637, 298827430321256, 336098642729624 @ -33, 31, 46
+367582428636269, 353752754593133, 455721090356150 @ -22, -10, -51
+211477679844979, 203677879111232, 217560677966690 @ 21, -6, -258
+218366027555690, 91153932623633, 169742494255475 @ 55, 516, 174
+288792682769846, 151081271429165, 316680362356580 @ 29, 198, 39
+400036733736580, 365852984506581, 406363416106765 @ -121, -82, -86
+243674722027939, 264638195629846, 368019298840514 @ 48, -10, -195
+332472697757909, 255887072597627, 449982813510170 @ -14, 72, -103
+293819507985671, 365421753329232, 320423714581815 @ 40, -41, 64
+183795219388603, 164835194289157, 182094814151316 @ 164, 184, 203
+366382639583285, 522460208371841, 518912456550689 @ -38, -210, -150
+278030923313372, 474502522717304, 278007597919598 @ 25, -273, 61
+184999670575064, 304820097537788, 122671272945698 @ 173, -157, 321
+265320160337191, 209979205841084, 187675399475264 @ -18, 93, 162
+255003872135235, 187028804687876, 407151799392366 @ 42, 150, -202
+232101686193635, 213975266196382, 240273621582836 @ -56, -16, -240
+240450116917919, 291888137519462, 173873024655080 @ -126, -500, 110
+272272783256099, 179409072253472, 234062260919450 @ -131, 168, -51
+258328493647231, 291203717558176, 1069885971366 @ 6, -85, 583
+308480795834427, 375221170112166, 191413358004718 @ -148, -344, 143
+318965385523139, 449168722347464, 524505928207346 @ -77, -325, -428
+315428275959716, 320608674825977, 347102330296784 @ -13, -26, -13
+265804330221453, 202452363951731, 254036584668891 @ -70, 96, -68
+248444418711669, 229841285103942, 226914597591080 @ -19, 10, 12
+227395285887150, 257325944365101, 70101971531074 @ 15, -148, 577
+224719946426892, 475040312860836, 153333865934499 @ 69, -613, 242
+344114892644297, 270105569149106, 304267086374202 @ -101, 12, -7
+320857919431207, 217110959414744, 196143006133728 @ -24, 111, 187
+410690148490391, 362551894817732, 320880138922346 @ -121, -66, 37
+315678167593799, 310902164439092, 311011187282990 @ -153, -162, -150
+284162696329517, 416472913289144, 295799028470984 @ -215, -793, -340
+129718901789310, 163245969554691, 216967791295737 @ 249, 188, 146
+209964965625112, 191161250819537, 165388796738017 @ -25, 54, 82
+497673110723211, 386499996540904, 291331122466962 @ -160, -49, 106
+320457813756275, 281605309858328, 237722774472098 @ -190, -109, 15
+259221111410294, 226809538368362, 251163917228960 @ -33, 33, -33
+151145084542716, 130981648419475, 211580753667646 @ 231, 256, 133
+239808287365644, 261920251496762, 276405310385540 @ 77, 33, 51
+197726725612939, 82924950628456, 179987257304506 @ 123, 983, 5
+241050954384837, 183215659641108, 354255673424906 @ 77, 157, -63
+244313293798068, 247257935609159, 212779037837148 @ 41, 18, 115
+65408297713475, 57213841527206, 185313960119735 @ 316, 321, 204
+213464627894059, 86598732993256, 266870833653114 @ 78, 515, -185
+231737597144849, 223510555290722, 213894690906560 @ 35, 32, 56
+353131713528389, 301010156323777, 361300184449735 @ -122, -44, -110
+210230261973787, 92476419248104, 254715385528386 @ 62, 655, -328
+227008099340099, 156979790581134, 224213055692070 @ -32, 298, -161
+210017680134353, 191191733968714, 160479904438100 @ 31, 88, 174
+304280239427448, 321473363430832, 334898721210818 @ -9, -41, -15
+267558481716839, 268029989177432, 305049430365950 @ -11, -29, -88
+186217090156385, 109133442305270, 122793773229323 @ 166, 313, 308
+318213640730391, 398018375578773, 495253231503708 @ 24, -58, -97
+290701720322309, 305430434394176, 150675954587450 @ -82, -137, 249
+196942378457994, 356313064568915, 330403621930505 @ 143, -234, -156
+317630064349157, 327988113634937, 420667383465542 @ 26, 14, -19
+307210663909389, 396745266168812, 269500404103700 @ -207, -519, -126
+247734440322603, 211037541638632, 425633703630138 @ 57, 109, -223
+404292354896369, 418044561757832, 73932436985270 @ -65, -81, 327
+272425529225979, 200503642613178, 271391578599980 @ -132, 92, -186
+211119943025843, 197686009410326, 183468803904458 @ 16, 32, -15
+205698363151069, 152042412981382, 160956188941830 @ 69, 374, 175
+157759514155969, 250333392643202, 205728726817150 @ 195, 72, 179
+308391291585438, 325079994122717, 432676155319375 @ 17, -6, -76
+309299635224904, 234127317978519, 219421624701989 @ -157, 20, 66
+382159216227129, 382889401056097, 319693115663330 @ -198, -212, -63
+218187489376571, 422566774358632, 312517190522922 @ 109, -241, -20
+247545110083163, 192432035403088, 196197001106778 @ -98, 110, 37
+231526899779747, 315440878619220, 226641908528446 @ 70, -124, 88
+173690679890047, 145807048939104, 165415502811694 @ 275, 377, 160
+198519142716261, 271107833643099, 382751271921538 @ 134, -170, -607
+220936088721894, 251944246360182, 173486893674620 @ 17, -191, 135
+230390644548207, 248868579304448, 211288187422422 @ -15, -147, -28
+185557903379714, 200461866178385, 177146250671711 @ 273, -94, -112
+290744210240235, 333443315805346, 368972996267237 @ 20, -43, -42
+211078204160215, 81389178033560, 299463705825078 @ 107, 411, -124
+437889692077409, 431112874926447, 380045465959360 @ -134, -130, -17
+268877207746427, 204087465743720, 314922911436458 @ 41, 127, 12
+199719087190451, 169213590684689, 228107271345686 @ 124, 220, -123
+282380236428839, 411656091846557, 282867940696325 @ 24, -166, 62
+397826856342987, 452211758080168, 330373331681146 @ -121, -199, 11
+374618586912560, 252615688384091, 414701055188645 @ -53, 80, -46
+213861282273674, 271929032410267, 423566291770375 @ 121, 32, -136
+274481283519179, 254578847470664, 317281064015738 @ 13, 36, -33
+213494888794309, 293466234266568, 228979385511382 @ 113, -49, 103
+343411682019371, 404942906921480, 178038706926192 @ -140, -273, 196
+192352243335947, 170795309733782, 156307732787006 @ 180, 309, 173
+296188169759365, 244256411093954, 149453488908028 @ -18, 57, 251
+189342492734919, 314014840719343, 122425570017245 @ 168, -332, 354
+247162649115539, 105998776931752, 333214071620470 @ -62, 463, -482
+207368289604003, 208550616378928, 178175262907962 @ 45, -58, 25
+223109276940134, 194283940821317, 192599536479578 @ -47, 74, -39
+175890421522315, 269264174469288, 334198472779386 @ 195, -59, -209
+217965898959803, 229627973114324, 176383436151842 @ 16, -112, 103
+115618946952539, 264179415714824, 26481777466214 @ 248, 55, 406
+322922863045007, 295218163052482, 234199770059264 @ -50, -16, 120
+293540216463294, 77079033898158, 331983113702637 @ 33, 281, 38
+347580151826636, 552610880311787, 325500008424131 @ -19, -246, 58
+169997064298997, 183812696371766, 110099209449658 @ 187, 156, 313
+199191323698459, 185261515441772, 160896059282387 @ 68, 99, 66
+353493761596321, 274698465927902, 301198392973368 @ -6, 69, 103
+186674991963302, 211874452513883, 182967030401237 @ 231, -150, -84
+242340518372339, 358344177251432, 181251080906450 @ 53, -193, 188
+374043770146209, 474774304086652, 94295788089290 @ -81, -215, 321
+210499382481801, 177512186318582, 184632182551292 @ -121, 234, -330
+444397067199886, 233002159853181, 134288115474889 @ -111, 106, 266
+306337577309473, 277387748008390, 284478350548201 @ -18, 17, 50
+346716070516205, 232116346089890, 353561940487520 @ -73, 86, -46
+450711584871453, 478200056201838, 284267394541492 @ -195, -238, 70
+431538441846127, 451724385734838, 427283549634395 @ -96, -119, -36
+219599688402249, 244730862987287, 209874941505970 @ -10, -240, -127
+201313427071907, 168601630138128, 157007435499682 @ 97, 262, 200
+438249143117269, 424119931464984, 298765861529975 @ -222, -209, 24
+215169786915563, 201505002135480, 247795730191514 @ 124, 136, 135
+370374106183235, 349924267180376, 381694662475748 @ -36, -17, 7
+198274936976747, 189679389651512, 155226209680754 @ 84, 19, 167
+188637865692515, 238710086408456, 187527962451662 @ 202, -345, -78
+298578119394285, 159415079993552, 314518772814076 @ -129, 219, -188
+262617744694139, 63095765371532, 374161116246500 @ 76, 285, 12
+263920711620104, 270806325768152, 303212833144640 @ 11, -17, -53
+290492632700775, 413091023502423, 485082862014038 @ -96, -430, -603
+291219299932034, 206595628820447, 367604455779400 @ 19, 126, -41
+260431613882226, 248229048867126, 329084622595363 @ -175, -167, -628
+439102049496769, 369530307923446, 371404950446290 @ -162, -79, -31
+257968558770714, 281078884795924, 298922329292961 @ 23, -37, -44
+301358802493335, 205733437684346, 324809104729369 @ -40, 117, -58
+201852329595883, 95473825297336, 94982116864450 @ 132, 353, 374
+467684639369729, 264376256912432, 256231916787770 @ -183, 59, 121
+283031177126147, 412491770424764, 186653148896594 @ 40, -123, 205
+339282828623755, 243512640245882, 349445006190022 @ -28, 84, 7
+282107071900583, 308553492651032, 334941273994508 @ 10, -41, -42
+394544352562829, 137506031622212, 227643979610898 @ -122, 219, 145
+406483682511589, 406376435436337, 262485321255614 @ -102, -106, 117
+398570174321774, 464861989857797, 436669770404120 @ -53, -120, -33
+277557227178647, 478655596305920, 329087019719498 @ 57, -167, 53
+188098681704873, 201182913552424, 196748682285509 @ 170, 95, 96
+220824434287762, 25912163965555, 46272290905758 @ 105, 416, 421
+328250628245255, 206059181314970, 421991677850024 @ -134, 108, -324
+318571081875635, 210542087415780, 503574925874530 @ -38, 116, -281
+191806143345159, 326028987539124, 309381155794042 @ 153, -88, -23
+384690549589466, 232452348649319, 511439032229471 @ -179, 72, -372
+198846084039554, 216265375378557, 225156974398801 @ 133, 34, -22
+185109670669244, 12706941956960, 43641783548659 @ 163, 423, 416
+221105344157519, 241810380655562, 395248454330840 @ 26, -118, -882
+262985831692337, 264306581492108, 233974019746148 @ -79, -115, -28
+352980202408139, 481807077700748, 275698734979682 @ -52, -220, 91
+245584314526803, 181910661443432, 188073598822350 @ 80, 159, 199
+486424326428553, 478483299284374, 489268124278546 @ -331, -328, -307
+84607269180419, 31310497114262, 102095256416750 @ 352, 438, 339
+249794844265187, 413492647270280, 434505095753282 @ 31, -333, -354
+253138459784132, 433721962579099, 314039773803905 @ -29, -604, -246
+57063184441840, 2848723329813, 179657077519134 @ 281, 332, 221
+212537612086449, 199942000207897, 231491111459510 @ 66, 76, -123
+276716997669487, 321230090257675, 98214025033957 @ -88, -242, 400
+217313988937643, 207066350283624, 159695593020282 @ -125, -145, 140
+373039254978088, 418351417170392, 440315880352976 @ -33, -81, -45
+205971263695199, 156423749157962, 235273358276780 @ 54, 372, -458
+169032049328168, 191375939510495, 174714756027610 @ 319, 96, 89
+241284760156765, 213633705299964, 273986496029776 @ 57, 97, 8
+231523435971360, 228489578131039, 235856183447107 @ 5, -22, -82
+252983542761269, 299480440400552, 285041416252730 @ 37, -65, -7
+438841029654131, 411233172046176, 488186907692295 @ -116, -89, -116
+476618445015599, 443378419493992, 235448704267905 @ -128, -97, 166
+548515148436339, 369212112656432, 411233084497090 @ -277, -66, -64
+235084601447111, 288801002347004, 254905125178070 @ -34, -323, -221
+210815474330455, 183771003173272, 169093337712866 @ -25, 139, 51
+223453610383232, 259282790436728, 100611635827082 @ 47, -113, 425
+409903837974191, 309320061210647, 410213620779925 @ -80, 24, -26
+200664501201994, 214208004490011, 170443224746393 @ 93, -140, 66
+252107434605449, 108528804920758, 136069139545022 @ -17, 370, 291
+343707687775007, 448008675359705, 288140729453288 @ -240, -534, -109
+506078467934517, 441535791803524, 207285945417846 @ -171, -107, 191
+355379228119331, 373167458767232, 479637645984386 @ -41, -66, -138
+193797798537759, 201906209762360, 108370558375644 @ 158, -57, 706
+193493291547483, 189753357420014, 304454307069450 @ 156, 108, -751
+227264523175811, 227535163030568, 220790078350034 @ 51, 23, 40
+217277712229271, 285062930429621, 291971345546024 @ 80, -152, -177
+354830252462459, 132099677502728, 201376420384238 @ -32, 215, 192
+185341031389468, 250460260179714, 41915697374578 @ 197, -199, 817
+294648208196255, 227863682383273, 245974501368731 @ -176, 10, -60
+175644806143963, 195231892463304, 162755375935978 @ 317, 41, 142
+196480732288294, 201591457358128, 194254859827134 @ 143, 103, 125
+531147271206795, 259617234789502, 399336989294874 @ -220, 74, -23
+173328857832331, 301587043811133, 192796692515747 @ 180, -20, 186
+487366811837399, 263146090734452, 462894050296310 @ -151, 76, -70
+287879979651467, 381808901282290, 461197492201210 @ 52, -47, -71
+93328649189759, 26248115804612, 49995133784360 @ 290, 377, 390
+292553050712949, 248133729492768, 220661696957771 @ 18, 71, 156
+247123755360443, 278822927710248, 126447888020746 @ 55, -13, 292
+205604258593800, 320800110216493, 242202181198269 @ 131, -58, 106
+207286557485215, 159193041484164, 211343065768074 @ -45, 508, -683
+261011778004939, 282090662850632, 360754912762250 @ -118, -243, -594
+366372507252833, 261730973147386, 313848450194648 @ -95, 46, 18
+200675222189585, 213195258457802, 163113489498041 @ 70, -251, 86
+229766991676604, 324420786234443, 132764846007159 @ 103, -24, 272
+233197540416981, 252663735890655, 189149976637092 @ 30, -58, 131
+551758591442549, 317434445725907, 414246348847160 @ -234, 14, -33
+266505418321892, 210846000959996, 327070235871119 @ 19, 107, -68
+415341778479239, 334137260920643, 498517411363879 @ -152, -48, -224
+341243266909844, 313402743468757, 271648670050749 @ -47, -16, 88
+429253377166361, 553469201787950, 476558267750136 @ -119, -264, -122
+285246964184633, 406063955848160, 236170320081561 @ 22, -153, 130
+227382783338389, 229593188301165, 291763979262386 @ 98, 86, 33
+371393091005381, 332181332422916, 414664971173030 @ -26, 11, -11
+295303657865079, 166167683087264, 226767016642262 @ 33, 177, 162
+190511535560235, 9219366352168, 296515859283426 @ 156, 487, -28
+320530971757025, 403540372078112, 334498243996214 @ -45, -181, -33
+369733277446451, 211936845599162, 168691665080888 @ -56, 124, 228
+231181433150507, 273561808328896, 306128452343458 @ 76, -22, -58
+214043005397259, 203645084352092, 174825313374850 @ -12, -21, 49
+227687623044354, 218571675056187, 199351922241360 @ 41, 40, 91
+402517424550319, 523219204178372, 439330837837110 @ -73, -204, -58
+392982884025931, 288312405947464, 441558421576890 @ -111, 20, -131
+401375240184702, 221198061028482, 541978454454548 @ -115, 109, -249
+460789113388994, 269555798627036, 307185128129600 @ -107, 75, 99
+146557416689339, 109661508926432, 103473174943010 @ 298, 384, 396
+209850871729361, 212165368167476, 162908120703152 @ -61, -259, 80
+283865324628374, 286310975082482, 336187281130685 @ 37, 29, 18
+363752349292959, 364338119210717, 424832473039980 @ -16, -18, -17
+172177969652473, 17105875767158, 304684280315760 @ 219, 678, -236
+259508908932596, 277357839909803, 259475847139790 @ 17, -34, 29
+202590478447655, 179288341416660, 234590195444154 @ 136, 163, 121
+235908430631009, 279316247590842, 216375695579495 @ 22, -139, 48
+255033321738497, 330823756187032, 145836279008283 @ -14, -241, 262
+294875061213557, 134131943755328, 259096890879686 @ 39, 211, 131
+228407861241887, 230478783727664, 201594147304790 @ 19, -27, 54
+293412677139998, 451626582277610, 496863056041280 @ -43, -363, -421
+215706007850474, 234310175720234, 185835801829460 @ -37, -303, -61
+172787440253597, 192472476831530, 116146942741745 @ 310, 81, 504
+214750602238147, 195161664305320, 243432974620666 @ 15, 71, -367
+195110086900331, 196922406141288, 197386318990650 @ 142, -74, -476
+192828459228011, 174093542493704, 164809937334938 @ 172, 258, 70
+377690397113389, 537389168721472, 490471586544400 @ -202, -521, -401
+186436861369681, 155775820143126, 5978174705268 @ 161, 200, 476
+213571050502796, 305021137306949, 172330565977124 @ 101, -148, 195
+221845157530388, 255456728002691, 173155151010878 @ 37, -142, 157
+205679143768689, 317760416420172, 87602854062535 @ 78, -709, 652
+233972821255379, 305083270506712, 274805863721170 @ 25, -227, -140
+235592283807893, 410990846676011, 457908691276527 @ 34, -480, -608
+417252866685453, 394738457791274, 359865668946440 @ -219, -192, -96
+206500202846264, 256535196755432, 135051442506500 @ 47, -481, 383
+185695536952651, 191208134840648, 195546369678362 @ 215, 90, -84
+210713655879539, 211225913549132, 198113362540310 @ 58, -6, -18
+261292203869294, 323241101432198, 456891907896443 @ 83, 21, -50
+251060694976859, 281909149925330, 358419293335055 @ 68, 17, -46
+298270977956133, 349728958018374, 373151928770270 @ -229, -452, -561
+364728658142934, 339476400747642, 445075099076895 @ -57, -31, -106
+238259352607679, 402592303972052, 82369731900020 @ -26, -723, 522
+327011202003754, 358835293546122, 371425954275210 @ -15, -59, -23
+308572379501567, 326520914026184, 270233115165734 @ -211, -297, -128
+189003777687369, 279146253002922, 159255565607405 @ 158, -11, 234
+470070380998654, 398687409040702, 362740164193475 @ -261, -163, -66
+176058988255331, 218202803327892, 229481748393706 @ 184, 89, 97
+283701401834475, 286339794135400, 243383449936442 @ -19, -37, 75
+322209744902375, 285151041214136, 389223801784910 @ -15, 27, -56
+370122298772019, 365467524657632, 201663972146950 @ -24, -21, 199
+284873297928479, 217970573267888, 100592743720150 @ 58, 123, 299
+202597289456237, 252168926544368, 139168135303676 @ 135, 43, 268
+230650641748533, 194871712283483, 191832975676033 @ -10, 102, 68
+193383620827930, 211491476351923, 181596667035350 @ 161, -128, -51
+408278509872299, 391228450735992, 334570530605610 @ -104, -88, 32
+190463197800155, 274896788605448, 201892417058162 @ 194, -845, -304
+217407649288665, 217873308026022, 305591970635530 @ 107, 94, -31
+233541543357494, 224991057805055, 135605427238331 @ -107, -124, 348
+365473205546095, 299518864347167, 310100407412513 @ -48, 24, 66
+191333573404187, 145083532071008, 68084568212474 @ 170, 398, 785
+501927382552429, 488197499168268, 518403565149304 @ -187, -175, -152
+332536358436865, 104281909758699, 306805691121913 @ -10, 248, 70
+358093525295609, 378428206009322, 256432384193190 @ -59, -90, 115
+266809407954339, 256879986613912, 325844666283860 @ 48, 55, 6
+325628425277326, 507254127151315, 192036788366827 @ -159, -604, 152
+220086170001408, 145737699276809, 51304253922819 @ 87, 246, 488
+200496566225063, 207408289481713, 147102163056478 @ 64, -212, 301
+532796896719425, 517023677463188, 472763376344954 @ -423, -407, -295
+358660863901069, 369116533440014, 330478204527670 @ -162, -195, -91
+314424345559373, 423625375290148, 194045819512100 @ -59, -259, 174
+259707879828127, 253646644874172, 219036127033214 @ -6, -11, 87
+194944304770111, 207577080765677, 149627219174283 @ 144, -306, 268
+227417712097544, 221143693919678, 251872268514275 @ 43, 33, -76
+336409926796047, 244516283772396, 345082887082654 @ -24, 83, 13
+183637429237578, 207938870704610, 326607369038005 @ 171, 105, -116
+209827782077099, 199028826981160, 202030451200634 @ 88, 91, 45
+209472323005991, 424563613950778, 281308224244082 @ 106, -532, -123
+278630950990928, 399877095615054, 313668553591893 @ 61, -67, 80
+273765578214239, 284236428842132, 191116078230050 @ -110, -175, 117
+285848786770827, 241340184315272, 438909140515874 @ 56, 99, -42
+249240240321872, 176846266507765, 280264883823635 @ -35, 176, -186
+347784136150549, 335776861425501, 454380443557293 @ -42, -32, -128
+205264221468995, 189072934063788, 218109426994198 @ 70, 106, -250
+286964297738209, 232956529638962, 280081708170855 @ -58, 45, -40
diff --git a/2023/input/day25.txt b/2023/input/day25.txt
new file mode 100644
index 0000000..a29926f
--- /dev/null
+++ b/2023/input/day25.txt
@@ -0,0 +1,1211 @@
+zsx: lrs
+nvs: vjp
+rqb: gzc dzr
+xct: vrl
+kgf: vkl lcv
+ksn: vsq vkk
+vgz: spx rsd rtm ljj
+mzp: jmf cfn zpf
+lfd: lll nps bvl tgc
+pts: sgk kgd
+zcp: fqp
+zjc: kjf szz qkn pnn lnk
+rsb: trt rkd rcz lzj
+cpn: rdx dmt
+shs: qxs rdn pnm bcf
+vkx: lhr lvg xvg gxx
+xpn: bvb hxx jxp bdg
+jms: jzp ztv rhh qjc
+jlf: jcq gzv
+xbx: bng
+rvv: hsm mhp hgr jvm vkz jvr jbh
+clm: ltz
+kfx: nmm kvq cbl mhn
+zhn: tdl bxr khs ggp rkv
+lcd: tld zkd
+zxl: tkp fgx bvl qlt
+knm: tlj
+kdd: lhz pkq
+jlj: zqz hsm tmr
+fnn: gzk mjf brr
+mpc: bbk xcr sdj sxg tdd
+rpd: vhj ssx rhd zlx
+jvd: skg fns vph
+sdt: kvq
+pns: ltx xsm
+tbq: hnh pmc nxb qfj mts
+nvz: tjj ltx
+jqm: gvj vjj jvk rvf ckj
+lcz: zlx qdl
+cqd: hzr kgk mmc
+jvm: cml mqd sqm
+jfp: glz
+rqj: bxj fgn rxh
+gcb: ght zzg
+hfx: jld bnr
+cct: chv dml
+mkv: dkd
+gxx: vcf
+fmj: hrh tjj
+kfb: ccx zjs
+gsp: qrn tqb pzs nzp
+bdk: xcr
+zkm: xbg pmk dgd nvb vhs
+kkq: nxf srs sql zsx
+jff: skf
+xvb: cdr cfn
+xqm: bkg qbr hnb
+jbh: clm
+tkh: fqn qrv bxj
+snx: lbj nnl vht
+gvj: tmc bjl jlj
+ttj: rmk nhp btf rcr
+mcr: jnb rkv jgp qct
+cng: stf ctr kmv
+mhn: lll
+krk: ggx kvz tzh zdq
+rnh: mrq kct vqt lqd
+mzz: kxr sxp vzx tpb
+mqm: znm msl krz mxv
+gbk: tlz xqt xcx
+dph: xkc fmv
+vkv: hsb lbh
+rcm: knj mjn
+hlh: jpf sqg qbr
+zch: ktt pfb cpx
+sxg: tlq
+qqg: rsd vgd cbl qxv fjh
+mtq: hfx vzr pdp
+dlx: hvh sbj vmm xnc
+pvl: psg hbt
+fkx: xzj
+gtz: ldv xmt
+lpm: nqg plg cxg hdt rsk
+dbn: lhg zhc ssx
+spj: zgz bgg qdf fng
+glz: cmm dml zjd
+ssl: jxc
+ltn: nfr lcz tzf
+tbv: zjf pmg dxk gzx tzb
+lrr: hdh stn qcj rcm vdc
+mhs: qgf stj
+kfp: bjp hzt gqj
+sfm: xbg hcv kkc
+bbq: mcx tkp nzz
+vmm: jpm
+mlt: skn jkz tqr qkm
+kbm: prf fqp vcm
+lms: hbh tjl
+xvs: zqk
+lvc: sdg
+nrf: ddk ksn sgk
+kcj: xdp nzv pvd ctb
+glf: knp kbk xlv
+rzv: cfg
+pgt: knj hrh
+hkr: sfj ppr tpg
+pjg: rrb dgk qqq qkm
+bxq: mcc pjx gxc msl
+zmk: dzr nlm dtl nkb xpm
+jlc: bbn lnk gff fks jbn
+blf: rsq kfp hbd crd
+mqb: mtt stt bjl bzh
+tkk: ksc bzm
+hxd: gfb tvt dkj pxl
+lkl: bgk kbs qmm
+zds: jkt cbs drf nkz
+xkk: tfj njf
+hxv: lhb vsp nzf qmv
+qcb: dkq
+xkr: mvq fxb hzr ncx
+ngd: bbk zdc
+nfb: npl jsh tjb gss hgr bcq
+qtn: vzc sql gxs crg
+mqr: nzp hfs qmm tkh tgh
+xvr: jjn tzf pvj zdr fbh
+bqj: ddn hxx qsg qdl
+nzp: stb jbp
+qjc: jfj rhg
+sft: xkz njs
+hrq: jbf svr lsj qdb
+tcf: rkd tfq lcj
+khs: vst
+pvd: gms
+bbn: lfv fsq zvv sft
+dls: sdc bjn djf zbf
+dcc: qlf gms
+xvg: pxq
+jbb: pjd
+jbn: khd kht fkx
+kgd: tkp gnt
+kzx: rzf mkv bdr zlv
+xgz: dgd ncx
+jmh: cqv nzv lmh bdk
+kqd: nnm brs
+czr: tdv pjd lhr
+gms: zzg
+fnb: zff ffv mvg cmh hmg
+fsz: mxq gzx nfr sjx
+drt: hgq vgj tfp rhp
+zvb: zjs
+gff: dgk svr
+csv: qbr
+hhx: str
+hlt: khd zpr fbq lsj mpd
+xkg: xgz zrp smd
+vdd: cpx
+zjx: brr btm ggp hvg
+jkx: tcf mps mvs kvs
+hsg: rcb fgx njd sqb
+rql: vlk qrv hzs lvh gss
+frj: jff vdc
+bmq: mrv vjm xtj
+vpg: qgf vxt cml xhp
+vrx: nbb btm
+rth: jxc vlz grr mzt jhd
+zbf: rkd xjs kgl tdz
+fls: rvf nnl pvv csc
+xtn: fgv nst rkv lgf dmt
+xkc: zhc mkh
+mkn: fmq pjx vpg xkk
+lvg: vhs xvg qgk tdh
+xjt: ddn bcd cgk hfh
+hnh: jsk tht fcd
+fdq: rfc djz
+qvh: hsb lzd ltb
+kvs: njs jpm djr tll
+pfm: njf kcx lms smd
+cqg: tlj qhh
+bfq: cxf hcd lqx jlb lrr zkt
+cfg: qrn hvs
+pnm: ssx sxp zgh
+sbj: qjv dxd fnm
+nxf: zmf kbq hcd lfx
+qjr: vld xkz nmx
+lrn: hbd
+tft: fkq
+ncp: ntf dqt rpl zgz vqb
+nkp: plg cql ddz
+xlp: cpt rkd
+qcg: ttk mmh stf crj xvh
+bnr: zdc
+tht: rdp xzq
+rdn: gsv kzb xtm jrv pjt rct
+mvt: sdt jsk
+bfn: fkq fhl kgk
+pjt: ccn xzb
+qcr: dpc tzb
+vtr: hzt xsj ttx nbd xvr
+bjp: vrv
+sfj: qhh
+rrb: kdp hbr
+ctp: tlz rxt xdp ltn
+kqg: ndr zbf bkg bkt lqm
+tnn: vzx
+hxn: xvz
+tgb: htd qqj
+ddp: mxv bss vgh dkd vmm
+kcn: fkp fdq qqj lbj knm pkf
+zjq: vdg gql dsc
+lkf: kxn nvs mqm bfg
+lzz: xlv tgm stf tnn
+lgk: dkq hdb
+tdl: mdg xbp dtm qsb
+srs: jpl nvz
+ptc: xsj
+jls: xcr stv sxc vqn
+jdf: bbz jxn srf
+lng: hhx lpn tvt vfh
+bdc: dpc cpn kzf shr
+ldc: fmv msn dxv
+thv: mql mlg htj
+zrp: vsp
+qtg: tpb
+kkh: jpl ffk gbk jdj
+hbn: ffg nkd hhx
+qqq: vdd kqb
+qhh: msg
+dhj: gqr gqk fqd
+djh: bvp xjn hns rsk
+fbb: tcl vht
+kvl: cgx znm dxd
+tcl: mcc
+dms: kgd hhh brr fqj
+rvl: jrv
+kbk: vlz jbz
+kfq: njf tvv plc
+jqr: gqk ntc dsc bkg
+qfv: vxl vdz rsf
+gtk: rsq jff blh mcb
+ggp: xzn
+pbk: rkx gzj vld hcv gnm
+xcq: htq php xpr fxj
+qcf: qjc cvx ptc
+gqx: nkd rbt mcx hzt
+sdj: cdr dkj
+zkh: xmt qrs dxv xmh
+tlz: nlj
+xzn: cbl
+xfj: vrk xct jlb xdr
+qzz: nxl
+bkl: kht nzp qjv lbj
+nqg: hfh mxl vgv
+qmm: ckn jfp gnm zrp
+bfg: plc cmh fxx
+bzt: ldv xkc mjm
+ksp: clf jdf gkr zgv jgq
+vgh: qzz nvs gqk lqm
+xsp: qvz
+qdm: tjb xsh
+brm: sdt zjs rdb
+nrj: gql
+qxs: vrl gcb
+nvb: cpx
+bkq: vlf rmx zjh kdd gqm
+grs: kbs
+krn: nnm kkc fgp
+tbx: xtg
+qct: qjx
+htj: jpf dzr dsx
+pmb: jcb
+pvj: ffg
+xmh: xqt hhh
+bzh: bxj dqg
+pdr: skn dlr
+djk: fgn mth vjp
+fsh: rkd bkt nnp scz
+kqp: vrx dft xbx bpt
+gqm: hlh sqg csv
+bmp: mxg fbb kxq vnq
+zvf: xkm kht rhb qvr htd bfn jqg
+rkh: xkc vqn
+rvf: sfj
+tsx: pzs pvl jzf kqd tcp
+spm: pzm sft
+fgs: kqm rdf gvm
+mnq: qcf dms mtf bhh
+xjj: fms ztv cbb zfr bdk fxv
+qql: gtz tfz lkb mxk rpq xbx rhh
+qjj: gvx qnz dph
+ggg: rrk bkp xmt pmb
+vlf: cpd khg xlp
+mvn: dlt mjj
+gmb: bvl thz tht
+zjd: zvv
+ppc: gmb rrk kmv fcd
+vhx: njf gbn qrv
+kxc: sff
+bqc: lms vht pcc mvq
+bzn: zcp
+zll: bxj kxn xrm
+mbp: qqs ssl vrv lgz
+mpf: fjb rhd rdn pls
+cbq: cnj xvs
+jgp: pgt
+msk: bpf rdx pdp qsb
+prl: rkh mbl sld
+bzk: stj fnh
+jqg: nlg gql djj
+jld: ddk ttk zdc
+xdr: ctr
+kgl: vkz
+xsh: npm
+kld: bht cpx ntc khb
+trt: sgv
+qjd: jgp rcb
+kvf: bvp ffg
+rnt: zrx mcd pgk
+lmv: rsh kbs dsx
+sbk: kmv ddk pfj
+dss: zgz trt mps sds
+bdm: hbh hvz ckn rxp
+tbf: mxk lgz gnt xqb
+mqd: tlj pgk bnx
+nhf: mxq xbl kfb dfk bkh
+hqt: qxd jxp ngd shr qrs
+jnq: khn kvq bvb gzv
+bct: vjn lmb bnx lsc
+dsj: vkk hrh fjs
+pfx: dkd bnx dth
+ljj: ksp nzn ssl
+ztr: cnr
+qvz: fnr
+hll: qzz xgb jbb mkv glp xnc hbr
+tqr: psv tft ndr xhp
+vpb: trs rdf bmr vml
+vjj: rvk
+grz: rdb sdt nst
+rdb: tgc
+rld: llv hzs fkp
+kmr: ltc vhj hhh
+xgh: vfh lvc vrr pkh
+dgr: mnk tcp
+rqz: msx rxh jvd ztd
+fct: mlk vrr xff
+qgj: jds xzb
+btf: sff
+lsm: npm qsc jxs nng
+zkl: gbh pmb cfv
+dsr: kdp crs xzn jsf djj
+khj: rlk sqb tgc fvv sbc
+ghz: zlx jcb tmz
+ftv: bvb sxc rcm khs
+sgv: mnk zcp
+tmc: fmd qnr
+sxc: xsj
+nkk: fth ztr fnh kmd xtc
+rfg: kgk jzf fbq clm
+tdd: tld gbl jml
+jkz: zjd cct
+xfp: clf nvn hhq
+fqn: rvj zjd
+khg: tbx pxq
+fhl: npm cpq qbr xlg
+fvv: bcv jff bql lcd
+psb: kxn pgc fgp vpk dzp
+fnx: bgk tjb xnc rsz
+lpk: kvl qtt hpp mvs
+tkp: dpb lrn xbb
+ccn: fms str
+ltb: qsb dsj fmv
+vqg: vcm pgl lhr
+zdr: rdx gbl rdf
+phg: jcq jgm kbk
+nzn: hzx hhh jfj
+cfr: mml gzk qhz tfd
+mlb: zhj pxq
+zqf: kdm fxx vbp
+vxl: bxz dtg njd
+kzf: mpz
+fbq: qmv lfv
+sld: cvp zgv dtm
+grj: ntf jfp kbv msx
+gbn: vkl tlj smx
+vlk: zms fqd hlh zrx
+cbs: tdh mcd vcx
+kmn: sbc
+dxd: lrp
+rsc: gkr zmh bsl kmr glv rdp str
+tmr: xsd chv bqf
+gxs: mbc fjf glf
+mfg: djf vqg ntf
+fjb: hdt vkm
+rrr: hsb htq
+lsp: jqg gxx fmd krz
+vdz: bjx vzr dlt knp
+sgk: rct pbc
+xdp: qjj nnc hgq mxk
+nkh: fms
+prj: vst zfc nmj
+dqj: znn hlh fqd zkp rhs kbm
+khb: rhb fng
+vmr: rvf hcv bnq djx
+cpv: qfj
+xms: khg
+ntb: xlp pbl
+rsf: jbz mjn lcz
+pdp: gvx jcb
+cvp: plr
+bcv: jfj
+zrx: nnm qfj rzf
+xbg: nxl
+djx: njs lcv nzf
+rcz: mhs sqv vbg kdm hzr fhl
+tml: jgq nzv tzb fgs mjj hrh
+rpq: xjn nlj tps
+pcc: tbx lcv
+nrq: clx bnf chd prj xfr
+ntf: vcm qpb plk
+kxr: rng nps
+smd: grs tll
+crg: tzh bqj zkt
+dgd: rvk
+rlk: dmj sbc ztv
+smh: hnb
+hdk: qcr nzn xld mbc
+mjf: qcb dpb
+nbc: kzn dhf sms rzf
+zhb: gzc qqh vhx lcj
+khd: zrx rqb pgc ppr
+mms: jgm ggz
+csc: bxj lfh mpd
+fkd: hgn sfb rkx xsh smx
+jbp: qxj kqb
+hkq: hdh pjt gcb
+xvp: sdg pgt
+qvr: xkk pcc kxq
+xcc: ntb xjl stt vdg
+krt: xjf zqz zkp tdh
+bcx: xkc ggz
+ffv: ltz
+hcd: xkc
+bcq: qhh
+qqs: mjn
+znk: bjl lhr
+msn: dph
+mlm: bqb gqk
+kqs: dpb tnn
+xrx: nps fcd
+vgx: hzr lrp sfj
+jcb: bvl
+pph: xcp prj ffg mbt
+sfb: bnx kkc jqg
+gjr: mjj kvq
+nzd: xdx kmn xqc chd skf
+hzx: cnl krf
+fgx: dkp zvb
+xdj: kfb rbt tjj
+lqd: pzs vcf
+qgf: kqd zkj
+drf: brj
+bbz: fjf
+kqj: kqb clz fsk bgg
+dvj: vml jdf ffk mvt
+vst: qjx
+nrv: bxr vrv jzz sqb
+hvn: lrx hgr vxt vcm
+lcx: cnr pgl kvs krn
+hrf: rgq qvh vsk kzb
+pkt: phd xct vgb xbx
+dnz: jgm btm rdf flh
+vxs: jbh jfb kxn hmg
+zgc: nhp vzr bmr cvp msn xfj hxn njd
+lkb: vrv
+zkp: grs
+mzj: krf zgh mzt clx pts
+nlt: cxv jxn mcx
+lsc: pmk crc
+brl: fvp qvz kzn stb knm kkc
+qlt: qlf
+jkk: zjx sdg jrv php
+jqk: vsq lrs rng gxt
+tdz: vhs xpm
+fkp: zrp psv hvs
+gkr: tmz xvh fmv
+xtf: pkq lfv fkq
+ddf: qcb zfl qnn
+tnh: lmb qqq znn ncx
+gqj: mml sbc
+bvb: jxn
+nkd: dkj pvj
+tld: knj bdd
+bkt: qrn tcp
+vqt: spm tgb
+tbc: vlz zvb vck qcg
+dsx: lsb bnx
+gss: bnq
+fks: fqd hbh mhp
+xzg: jxp xmh qqs
+rct: jpl
+xlv: gbl
+cfv: qlf
+qvm: mlm bkg pkn
+xtc: cqb
+bjx: vgv
+lgb: jlj fsh clm fnm
+pcl: skg vfb qnr
+rcc: lvq mnk qdb bqb
+sfd: rtk mxl bhh xzb
+gcd: qsg qtg pfj
+bgg: vkz qrv
+xmj: lgr rcm scg cnn
+tqb: njf
+fqv: lrp skn zvv
+hfh: cbl nlj
+jxh: nvb
+sdc: plk tjl
+lql: dbn xfp jmf vtr nmm rhg
+fxb: rxz zqf zpr
+bdx: lqm ppr tjl qnr glp
+vqn: qlt
+nzt: kbq jds qsg jxp krf
+xkz: fnh tjl
+lhg: qct grq
+nhq: mcb xqc tmz xvb
+bbk: rfl ldv
+bjq: lzj pxt qqp hkr tfq
+rzj: cfg kqb vcf bgk
+xfr: pmd vrv qcb jlf
+rsl: lmg rdp qlf pjf
+rfl: cql jxc dkq jgm
+jzt: hnh mvb lmg sdx nzv
+zkd: qjc zfr
+bdg: rbt lmg
+zmh: dbh zlx xvh
+nmx: nvs dth gds pkq
+xsm: vhj nnf xzq
+nnl: qfj
+rpl: lnk tcl
+tlq: xvb ccn
+tbj: qss fmj bbz nkh
+nsd: lpn hhh
+znq: zgv hrf pjf vzz
+nrl: xsp zfd pkr
+mbl: ttk
+qjv: jgk
+qjs: pbl
+trs: gnh jff lss
+msx: qvz znl
+zfl: jcq
+dcd: crj hxn zlf qnn cgk pmd
+snz: xtr ltx vrr bdd
+mbt: frj bbz
+xpf: rjr
+bsk: zjl lsm dhj psg czx
+lzj: skn pcc sth
+npl: npm znk
+njb: tcl xbg kqb tkk
+mxt: vxl sxc nst jgd gbh
+vhs: xtg nlg
+kgk: qxj spm
+sdg: rvl
+rfc: lms tmc
+ghx: bzn hvs
+lhz: cnj
+pmc: ggz pgt lmg
+qjz: dml cml
+jzf: rzv lmb
+nfr: nbb dfk
+xff: mtn khn
+rsh: fgn
+zlf: qct plr pkt
+mnx: lvq clm
+kbv: tll cpt sdc
+kcx: rrb jxs bqb
+pkq: hbt nvb
+cbb: qcf xpf cxg
+mth: xzj
+xtm: dlt ggz
+srg: hzt gbh mpz plg
+ggx: zgv dlt grz rkp gbk clf bnr
+lgf: cpb pqc nmj hhh
+mbf: tzs hbl mzj hbd
+rdq: vph dsx kxn
+jmn: htd qvm pxt qdm
+xqb: gjr vrx cnl
+mqh: znl rnt hgr ntb tmc vlf
+rrx: fct xvk ngd zfc spk
+rhh: xdr
+rcr: bmq xvz
+zqz: rvj
+zvl: lnh spx
+qkf: smh fhl stt tjb knm
+fnm: sqg scz
+xcx: lll ddn
+ght: grr qnz
+dtt: tzf bcb rdx ztv
+scg: gbh plg
+rfh: hns pbc fjs nvv
+ttx: kgd mzt lvc
+zzg: rhd
+fmb: ghb dft
+tgh: bqf pvv
+ktj: lrn cfn bkp cxv ctr
+zjs: mpz
+bbg: rvl fbh dxv
+dkd: jkz bht
+bjn: qqp zxs mlb
+pfb: fsk
+xbf: cmm nzf pgh prf hvs
+xjp: vlz mcb gbl vrv
+ltx: bng
+czg: jgm cxv rhg
+qpb: djx crs
+tfx: zhc
+vvd: srx brm
+rhp: bng nxb bxz
+rhb: fkx hbr
+qcj: str
+xcd: ztz qkm xsh
+fxx: pfb jfb qjs xpm
+qrq: xdj nbd mbl mtn
+jkr: mmh zsq qcf
+stb: fnm mhp
+jsh: dqg fgn vkl
+tfd: nps qdl bdg bcx jlb ptc
+mhj: tjj
+vtv: mmh qrs lxb vdc
+dxk: lkb
+tvv: bzh
+vcx: jpm fkq
+vsv: fgp stj
+dmt: pfj vsq
+ltc: ddz bxz cqv
+jqq: pxv zpf gbq bgs
+gfb: rhg
+xvv: dtg
+zmf: nsd rhp sjx
+qss: bhl
+bhz: sxp xvk qqs jfj qtg
+tpz: mrx mth
+bmd: qlf cng ngn tdd
+pkh: rjl vgj
+ftn: jqk hfx hzx
+fjh: mjn mlk brm
+chn: jvd dsr qqh mlm
+trb: sbk jhd lnh kqs clx rsf
+vzr: tfz xtj
+zjf: lkb nnc nqg
+rsk: rbt
+pls: mvm rrr cnl xdr
+vqb: rxb stj dpv mqm
+dsg: bqf cpx
+qqv: nnf dkq knp bzt
+cnn: stf njd qcj
+prr: vrr rsq xff
+lcv: bht
+lfr: jfp xlg khb jbf gnm
+xzq: vkk
+pmm: bqf tdv
+xzj: mps
+rcb: kzb
+drs: bnf rbt srf tlz
+chd: rrk kxc
+spx: grq vsq
+lbj: jfb rqj mvg
+gqp: vsp fqp tvv nrj
+vzk: zkj jxh qqp vjj
+rrz: hdb zzg hsb rhh
+pcz: jzz bhl cpb rjs
+pdt: cpv vfb gqt ksq
+rsz: xkg brs kdd
+kbq: zfr
+bkg: znl
+cfs: lrp vld njf pgh
+jmq: tgb kgf rld zfd bzm
+sth: rvk pvv fmd lsb
+mtf: jmr sph lrs qcj
+mzl: bcf ght bnr rhd fmj
+crj: zfl
+gvb: pjx nmp xcz ptj
+gxg: lsr frf vgh cfg
+kxb: bjx scg phg ddk
+bql: pjf pxl cvx nsd
+scv: tvx mml rtk htq
+mld: rzj gql sdc
+tdv: drn
+dpv: tql sds
+thz: lgz vgj
+fcz: mvg pkr tgj cmh
+stm: zpr xtf nkz
+pxz: gxc rpl
+tdh: pxq
+dqt: skg rkd
+xhp: fsk
+rmk: sjx bbq jpp tfx jkr
+pbm: cvx vbl bcd dsj knj
+hxb: rsk fck zsj xxb zhf
+gsq: zvl knp srg ncq kxc
+lzt: tfj skg lsb pkf
+xbp: jds tfz rbz
+mxk: dbh vgd
+jpj: hlb
+ctb: nkh gfb vzx nqb
+knp: xcr sff
+rqs: dbh clf lss nbb
+bft: dtg fmv lxb hhx sjx cqm xzg
+dbh: tld
+rjr: vgb
+ctq: dtl
+xpm: xtg
+lss: pts kzf
+mzt: dcc
+pgc: gds glz
+cmh: brs
+qsg: rbt rsd
+ngn: ftp
+trm: mtq hdt qtg nlt mzp
+dtg: srf
+xqc: mcb xbp
+nlg: jfb
+jmf: nvz ccx
+qqk: mmc sxs tmr msg
+nlb: zrl vmm trt pmm
+pkf: gds bzk
+bdb: plc cqg kqx
+pzc: bqf bdr kcx tql
+czx: vsp mpd dgr nng kdp
+bkh: llq lvc
+nhc: cdp bzm
+rkq: nvv cgn htq mtn
+tvt: qjd bgs
+qmv: znn prf
+tpg: tzj tql cpt
+hbl: vst vkv xsj trz
+crd: mvn nmj vjm
+bzv: kqb rgd sgc fng
+hgn: brj xcz vcm
+vfb: lrp
+mbh: bht tll hpc rsh
+sdx: vzx gbq plr
+gsv: tfx jpp rrr
+nlv: tdv zgz dgk
+qkn: fgp
+hfs: nng rkd
+stv: rbt dmj pmb
+tks: szz hnb jbf qjs
+hxl: ksc hzr qjz vtl
+bmr: pxl dmj jld
+gxt: zvb vlz kfb
+srx: dtm
+glv: msn ftp nhp
+mvs: xnc xkz mgk
+qtt: qmv mps nmp vdg
+xvh: lpn
+lrh: vjz xvp bmb
+jml: jpp jnb hvx
+ctc: rtk xvv tzs
+hzs: bcq
+gzc: dgk xtg
+drd: scz vcf vcx msg
+ftp: zjs nqb
+ksq: brj sfm kgf
+dth: cct
+zps: qqs gcd tht qnz fgv sdv fjb
+vdc: pqc bjp
+lrx: nrj rsh zjq
+phd: hvx mtn
+ccp: hvg xvz xvb jgd jbz
+vnp: mqb gqr tkk rmx
+bng: mvm
+rhs: rzv tfj vbp
+jzp: qlf kvf ngn
+mdg: bcd vzr nqg
+pmd: ksn nqb
+qxj: fsk
+kdp: kht
+dfk: cjg xcr
+fxv: rvl qxv bkp
+xqj: kqm fxj xtr jpj
+gzx: pjt
+pfj: nvv
+lnk: ltz
+fdp: bjp nbn kmn
+jmr: lxs nzz xct
+jzz: kzb
+khn: rdb
+zmr: kqx
+vzz: xpf rjl hfh
+tgj: bxj lvq cpx
+nxb: bcx srx
+lcj: pgh ndr ppr
+zjh: cpv fnm jbp vdd
+nbd: hcd lgz
+ldz: jgk pmm
+nnf: jgq vrv
+lmb: glz pnh sms plc
+xtj: tjj jnb
+bsj: ztr qdm xqm bzn
+gzj: rhs nxl djj
+nhp: fbh
+jds: kvz
+rmd: jvr xjs zmr xms
+pnn: nnp nqf cct xlg
+jjn: rjl qlf
+nnc: bcf kqm
+bls: jdj bvp kqs jcq
+scj: jds qsb zkd mvt
+ncd: gdh cqv vxc rdn gzx sqb fck
+flr: zfc cgk lrh lnh
+mhp: tcl
+cnj: psv
+lvr: ppr fnr
+skf: kmn xvv
+qqh: xlp xbl
+hdh: nlj bpf fjs
+kct: lsc ntc gjh
+lll: nps nvv
+zjl: qjv znl qjs
+crs: vjj
+fng: hzl
+pxl: xzq dkj
+smx: dpv
+mcd: mcc fbb rfc nzr qfj
+hmg: nxs
+hxx: mjm xvv
+szz: bjl
+cls: xpm mnx rvj cpq ktt brj chv
+mvq: gxx mxv hnb
+pkn: tbx zqz mql sfj
+cgx: hvz pgk dxd
+zgh: vlz kqh
+bmb: bkh dpb cgn
+tpl: thv tft snx njf cnj dhf
+cpd: pvl tqg qqj qdf
+ffk: czg
+rkp: kzf nxb bhl pkh
+sdv: dpc kvq
+gjv: jmq pfx msg nzm
+xgb: qjz nnp pdr
+vgb: mmh
+cfn: rhg tfp
+lnh: mhj
+bxr: qlt dkp
+vjm: khn
+gqr: jpm zkj
+sxs: kqx zkp
+xbb: mkh dxk
+nvn: gzk vkk
+gln: xjj bcv vqn nrf
+bpf: mvm
+nkz: pnh crc pxz
+vzf: lgr lbn vml pmg
+rtk: zkd pvj rdp
+frf: tqb fsq zjd dsg sfm
+fck: mxl xmt
+phx: qjd gdh sgj krf hns sdj zgv
+rkx: fdk dsg
+vnq: znk djk ztr
+sph: pns gjr nkp
+pxt: fnr
+nct: jbf chv tft hbr
+pjx: zkj
+gqt: clm
+lzd: blh vml kqh
+nps: rvl
+qbf: rjr ggp tfz bxz
+xjn: cjg
+djr: rsh
+vjd: jzf djk zmr cqd
+bcb: ssx nst fbh
+cpt: djj qhh
+ckn: qkn
+vjz: ghz zfr jsk
+hvh: bqf tzj
+pxv: xvk jbz prr mms tmz
+nmj: ssl
+nkb: plc svr
+zdq: ldv lgf fnn
+dzp: mpd qrv nzf
+jfd: rqs xvv nbb jgf
+mzv: fgp znk jkt
+nmm: njd
+tqg: znm xsp nmp
+ttn: tfp trz bxr
+rrk: vml
+gbq: hhq
+tzh: hlb lqx
+pzm: sms bzn
+cpq: zmr nxs
+rxt: jgp xsm jjn
+zlv: hpp kxq bsj
+jrz: xms sgv zll jvm
+pkr: crs
+qnz: mvm
+ztv: qss
+nqf: jxs
+mts: kqh
+jgd: tpb hdb
+mcx: rhd
+jkt: xvs smx tvv
+cxg: jpj gqj
+hsz: kvq mrv mbt blh
+glp: dqg qkm
+qrs: qss
+llv: jbb fvp rxb
+cnr: jpf djj xvs
+lxb: kxr rdb
+vbl: fjs tfp gvx
+mrq: crc qxj vht
+kzz: vdc jnb fmb hdk
+php: rdb gvx
+bfh: pfb zmr tmc stj
+rfz: gqt
+nbn: cdr xqt
+bsl: mdx nhp fjf
+ngr: hgq ddz lrn fmb bdk
+sgl: cnt nnp fjr sqv hfs
+nqn: nrl stm ptj nlg fls
+rjs: lgz
+clz: sqg mnk csv
+vrk: lbn kkh vxl
+djc: phd qcr cpj vgd npt
+fdk: fjr cpt jsf
+sgj: zsx djc
+tzj: qfj
+xvd: vrv qgj hkq rkh sfd
+pzs: txk
+dkp: qjx nvv
+jgk: djf
+jkj: nkh rbz sbk tzf qxd
+hjt: vvd sql qfv hbd
+djf: nnm
+mrx: lfh tgb drn
+jxn: dft
+skx: lll bhl tgm mrv jnb tfx
+vmb: bxr vml cqv bls
+brr: vgj
+jzr: vmm vsv lcv
+rxz: fnm
+cqb: xzj bjl
+ccd: nqf pzs zhj hbh
+frh: kmd plk
+brk: rkq scg kvq frj
+sqv: rzj fkq
+pqg: hzl vdd ctq
+nrp: ghx dtl ttm grs
+vgv: jrv
+kcg: bdb tcp njs jvr
+qnn: kxc cnl
+kmd: xtc
+trz: qcf
+mdd: jff zhc hvx ncq
+fqj: gfb zlx ctr
+fmq: sth mnx jpm
+rxb: pvv dgd ffv
+kqx: lhb
+vjs: nvn vrr lrr vgj
+ztz: bnq dlr kmd
+ghb: nbn xvk fgs
+nvj: vkl zjh fsq xlg
+bhh: qtg
+vjp: tll
+nzr: pzm csv
+gzv: fbh pvd
+hch: kzn vjn xsp nzm
+jlb: tgm
+ncq: zsx nps
+lbh: vhj mjm mhn
+lhb: bjl
+cqm: tgm nbb fms lgk
+hdt: mmh
+rbz: vgj mjm
+nxs: gql
+gbp: jpf dgr lqd rzj
+lsj: hvh cct
+nbh: xvp vvd zfr hgq xpr bhh
+qkm: vpk
+pcq: pmb lhg gdh
+nvm: gss hzl jzr vph lrx
+npt: kgd qdl trz
+kqh: rhd
+rxp: jbb lms zkj
+vxc: crj zzg ztv
+hdm: vgv sdv lhg srf zkl
+rxh: dqg smh
+kcs: mjn mlk grq
+bxb: xzn bzt ffk mts
+ppl: lhz zpr mqm ksc
+zms: fvp kzn znl
+xjs: hbr rvj
+bpt: vkk kqm
+mpd: htd
+bss: pgk bgk vph
+cxf: xqt rtk xrx
+tzs: mhj qjx
+xll: ctb zkt zsj phg
+qjx: ccx
+btm: kbq
+zff: nrj cfg
+cnt: nnl hbh cqb
+zxs: brs kmd
+fns: jsf fqn pkr
+zfc: khs
+bkp: rjs tjj
+dsc: mth ncx
+mlp: fxx kgl chv cmh
+ttm: vcf dzr
+vbd: fqv xcd dgk lkl
+ckv: mmh sff gnt
+txk: fnr cmm
+cdp: sbj svr nqf
+rdx: kvz
+gnt: kqm
+hqg: vqt drv njf sds
+flg: ltx lxs gnh
+vkm: qlt sxg tzb
+lqx: mbl
+mlg: qzz
+kdm: cct tql bzk bdr
+gbl: lxs
+gvm: jxc zsq vlz
+flh: dcc btf jcb zdc
+tlm: gff xbg jvd frh
+xjf: mgk vbp tfj
+gtt: lcd hvx thz xtm
+ksc: rzf
+bnf: hzx rbt
+stn: blh sxg hvx
+dhf: mlb jgk
+xcp: ptc tlq rsq
+mbc: gzk jzz
+lsr: fqp znm sgv
+mmc: prf kgl rfz
+dlr: drf
+vfh: plr vrl cnl zsq
+jvk: pmk ldz
+vxt: vpk ckn
+jpl: bdk
+tvx: rct bbg lrn
+vxr: lvr npl szz xpm
+tps: ckv vzc xpf
+bdp: cbq gjh bqb bcq
+qrt: rfz nqf gql cbq
+kjf: txk tcl gjh tqb
+qdf: ndr
+hns: lqx
+rng: kmv hlb ctb
+zsj: xmt
+nlh: nmm sxp vzc
+fxj: kcs mjf
+pgl: mxv tgh qqp jsf
+rdr: lbj tvv fsk ldz
+pbc: xcx clx
+fgv: rjl pqc
+nmp: tql
+qrp: pmd lrs pts lbn
+jhd: hdb
+kxq: hzl cpx gqt
+kmv: jsk xpr
+kbs: mps
+gvt: pqg sxs klj dqt
+xdx: jlb vhj
+xkm: dlr djr cqg
+stt: sfj
+xld: ngn
+cdr: ddn
+vjn: qqj mzv qnr
+lgr: qxv mjj lgk
+vkz: glz
+zsc: zlx nlh mhj tht
+spk: sgj mms vjm
+vbg: fjr djr hbh
+lvs: ctc xcp rkp dpb
+xvz: rjl lrs
+mjx: dmj srs cgn grr
+ddz: bvp
+cjg: pfj qlf
+rvm: nkb vbp nhc dgr
+qvs: ccp kqh rcr mxq
+sqz: xvg cml
+xtr: pgt vkv
+bcf: mhn xkc
+kxn: rvk
+zhj: scz jbf
+ptj: rvj nkz
+sqm: msl zvv
+psg: cpt
+llq: srx vgb rjl
+ntc: pbl
+ztd: pxz jvr tdz
+pjd: hsm vfb lhz
+cpj: zkl glf
+lxs: cpb
+mtt: zcp lbj bnx
+hpc: kfq xrm zvv
+shr: nzz jpl
+lbn: dxv
+rjz: mpz hdh stf hbn
+gnh: fjs dxk
+nlm: vgx fjr txk
+rtx: hmg lfv mgk mlb
+cml: gds bqf
+ctr: tpb
+lfx: qgj rrr xdx
+tjc: qpb tmc lvr nlv
+jmp: skg plk sqm mkv
+sbc: zfl
+qhz: zvl nzz nxb
+tfq: nzr drf
+rsq: gms hhq
+rjl: mrv
+rlt: vkx bdb fhl bzm jsf cfs
+sgc: lhb vld kbs
+mfq: kcs cpj bdd rcb gtz qgt zlx
+klj: rxz tpz bkt
+cmg: fnn ddf rrk qxs
+ddc: hlh ltz mhp qxc crc
+xjl: ncx djj tlj
+nzm: txk tzj zjd
+zfd: dth rfz
+fsq: smh sqz
+hjd: dtm rjr rkv pcz
+dqv: frf nqf zkj mhs zch
+gvx: vrr
+zpf: mxq ttk hlb
+rmx: sqz mrx qjr
+djz: mql cgx xhp
+bnq: fmd vpk
+xcz: kqb gqr
+zmp: cgn cvp pcq bcv jlf
+hvz: lmv tmc
+lqm: hbt
+lfh: qkn rzv
+fsn: jgq qcr xzg bcv
+hpp: mvg hsm
+rtm: zsq jpj cpb
+cgk: bjx mbl
+tdk: vxt djx fdq
+scz: vsv
+sql: zkt xld xpr
+qgt: glf nkh flg
+mdx: xrx xld xlv fjf xjn
+bdr: lvq krz
+xbl: rjr qtg vkv
+knc: kvf xcp jpp prl
+sxv: hzs zff nhc ctq
+lvh: ptj nrp czr
+cvx: jpp
+xrm: rfz kgk
+qxv: rjs
+drv: qdf psg
+vck: ztv pvd bhl
+mvb: mlk rsq tnn
+nqb: fcd
+lmh: mxl dft cfv jhd
+rvj: fkx zqk
+gxc: mps zqk
+pqc: xmt
+vdg: gqk
+vzc: cfv cxv
+ttl: dqg psv nxl mfg xms
+vrl: hbd
+mxg: drf sfm mld
+qgk: hbt nxs brj
+ndz: pxt pnh nng zxs
+ldp: mml lpn grr vtv ccx
+gjh: znn
+qxd: mvn qbt ftn fdp
+vcf: qrn
+drn: zqk
+jgf: cpn qjx sbc
+rgd: xtc cpv kbv
+gbh: mkh
+bgs: gcb gzk gdh gbq
+cql: plr mrv
+chv: fkq
+tgc: srf
+qxx: ztr pdr jxh zjh
+fqp: zkj
+qkr: brs cmm rxz qgf
+qsc: jxs drn jbh
+dfs: hxv vxt cmh tpz
+fvc: rhb ghx vdd gnm
+kpc: mlb jvk msl jxh
+pmg: lmg btf
+mgf: mrx drn tdk tkh
+bhl: kvz
+qxc: mql vbp dgr hmg
+ktt: pkq cqb
+jfx: dml nnp nvm drv
+qbt: rsd dpc vjz zsj
+pgk: mcc
+xxb: jzp jlb mkh
+qdb: rdq mgk rsh
+ckj: sds pmk mxv
+fth: pcl rxb ttm
+rgq: pns hhq bnf bdd xbb
+jvf: ctq xzj mlg lfr
+vtl: fkx xgz fnh qjs
+pnh: rvj
+xsd: frh hcv hbh vjp
+fvp: lsb
+zhf: hxn nps mts
+psd: dqj rsh rmd krz
+vsk: pjf vgd ttn
+jdj: mtn bpf
+hvg: bpt ldc dfk
+bcd: nps
+grq: xzb
+drb: dtl rqb mlg ffv
+zrl: sms pgh tqg sxs pbl
diff --git a/_freeze/2023/R/day23/execute-results/html.json b/_freeze/2023/R/day23/execute-results/html.json
new file mode 100644
index 0000000..fb2eab8
--- /dev/null
+++ b/_freeze/2023/R/day23/execute-results/html.json
@@ -0,0 +1,17 @@
+{
+ "hash": "5eb2d0bf642807840a3ce4bb271a21b7",
+ "result": {
+ "engine": "knitr",
+ "markdown": "---\ntitle: \"Day 23\"\ndate: 2023-12-23\nauthor:\n name: https://adventofcode.com/2023/day/23\n url: https://adventofcode.com/2023/day/23\n---\n\n\n\n\n## Setup\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Libraries\nlibrary(tidyverse)\nlibrary(igraph)\n\n# Read input from file\ninput <- read_lines(\"../input/day23.txt\", skip_empty_rows = FALSE)\n```\n:::\n\n\n\n\n## Part 1\n\nConvert text input to a directed graph:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Convert to a dataframe with IDs and coordinates per cell\ndf <- input |> \n str_split(\"\") |> \n enframe(name = \"row\") |> \n unnest_longer(value, indices_to = \"col\") |> \n mutate(id = row_number()) |> \n filter(value != '#') |> \n relocate(id, value, row, col)\n\n# Compute the list of directed edges between cells\nedges <- df |> \n mutate(\n row_n = row - 1,\n row_s = row + 1,\n col_w = col - 1,\n col_e = col + 1\n ) |> \n left_join(df, join_by(x$row_n == y$row, col), suffix = c(\"\", \"_n\")) |> \n left_join(df, join_by(x$row_s == y$row, col), suffix = c(\"\", \"_s\")) |> \n left_join(df, join_by(x$col_w == y$col, row), suffix = c(\"\", \"_w\")) |> \n left_join(df, join_by(x$col_e == y$col, row), suffix = c(\"\", \"_e\")) |> \n select(-starts_with(c(\"row\", \"col\", \"value_\"))) |> \n pivot_longer(\n starts_with(\"id_\"),\n names_to = \"dir\",\n values_to = \"neighbor\",\n names_prefix = \"id_\"\n ) |> \n \n # For slope tiles, remove any non-downhill neighbors\n filter(\n (value == \".\" & !is.na(neighbor)) |\n (value == \"^\" & dir == \"n\") | \n (value == \"v\" & dir == \"s\") |\n (value == \"<\" & dir == \"w\") | \n (value == \">\" & dir == \"e\") \n ) |> \n pmap(\\(id, neighbor, ...) c(id, neighbor)) |> \n unlist()\n\n# Convert to a graph\ng <- make_graph(edges)\n```\n:::\n\n\n\n\nFind the longest possible path from the start point to the end point:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsource <- min(df$id)\ntarget <- max(df$id)\n\nmax_hike <- function(g, from = source, to = target) {\n all_simple_paths(g, from, to) |> \n map_dbl(~ length(.x) - 1) |> \n sort(decreasing = TRUE) |> \n max()\n}\n\nmax_hike(g)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[1] 2074\n```\n\n\n:::\n:::\n\n\n\n\n## Part 2\n\nConvert to an undirected graph to remove the slope constraint:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\ng <- as_undirected(g)\nV(g)$name <- V(g)\n```\n:::\n\n\n\n\nThe graph is too large to simply run the hike length function again -- an overflow results.\n\nInstead, we notice that the input maze consists of relatively few intersections. Most of the maze input is simple corridors with no path decisions. We can reduce the graph complexity/size by trimming away our non-choice verftices and converting the length of those paths to an edge weight.\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nv_zero_edges <- names(which(degree(g) == 0))\nv_two_edges <- names(which(degree(g) == 2))\nv_nontwo_edges <- names(which(degree(g) != 2))\n\n# Extract all corridor vertices\ng_corridors <- delete_vertices(g, v_nontwo_edges)\ncorridors <- components(g_corridors)\n\n# Determine which edges to add to replace the corridors and their weight\nnew_weights <- corridors$csize + 1\nnew_edges <- corridors$membership |> \n keep_at(names(which(degree(g_corridors) == 1))) |> \n enframe(name = \"vtx\", value = \"group\") |> \n mutate(vtx = map_chr(vtx, ~ setdiff(names(neighbors(g, .x)), v_two_edges))) |> \n summarize(edge = list(vtx), .by = group) |> \n arrange(group) |> \n pull(edge)\n\n# Create a new graph without the corridor vertices, then add its new edges\ng_new <- reduce2(\n .x = new_edges,\n .y = new_weights,\n .f = \\(g, e, w) add_edges(g, e, weight = w),\n .init = delete_vertices(g, c(v_zero_edges, v_two_edges))\n)\n```\n:::\n\n\n\n\nView a plot of the resulting simplified graph:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nvtx_labels <- g_new |> \n V() |> \n names() |> \n case_match(\n as.character(source) ~ \"S\", \n as.character(target) ~ \"E\", \n .default = \"\"\n )\n\nplot(\n g_new, \n vertex.size = 8,\n vertex.label = vtx_labels, \n edge.label = E(g_new)$weight\n)\n```\n\n::: {.cell-output-display}\n![](day23_files/figure-html/unnamed-chunk-5-1.png){width=960}\n:::\n:::\n\n\n\n\nCompute all paths from the start to the end using our smaller graph:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nall_paths <- g_new |> \n all_simple_paths(as.character(source), as.character(target))\n```\n:::\n\n\n\n\nUsing the edge weights of our graph, compute the total length of each path and select the longest:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nall_paths |> \n map(\n ~ .x |> \n as_ids() |> \n rep(each = 2) |> \n head(-1) |> \n tail(-1) |> \n get_edge_ids(graph = g_new)\n ) |> \n map(~ E(g_new)$weight[.x]) |> \n map_dbl(sum) |> \n max()\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[1] 6494\n```\n\n\n:::\n:::\n",
+ "supporting": [
+ "day23_files"
+ ],
+ "filters": [
+ "rmarkdown/pagebreak.lua"
+ ],
+ "includes": {},
+ "engineDependencies": {},
+ "preserve": {},
+ "postProcess": true
+ }
+}
\ No newline at end of file
diff --git a/_freeze/2023/R/day23/figure-html/unnamed-chunk-5-1.png b/_freeze/2023/R/day23/figure-html/unnamed-chunk-5-1.png
new file mode 100644
index 0000000..3401e27
Binary files /dev/null and b/_freeze/2023/R/day23/figure-html/unnamed-chunk-5-1.png differ
diff --git a/_freeze/2023/R/day24/execute-results/html.json b/_freeze/2023/R/day24/execute-results/html.json
new file mode 100644
index 0000000..2f558d7
--- /dev/null
+++ b/_freeze/2023/R/day24/execute-results/html.json
@@ -0,0 +1,15 @@
+{
+ "hash": "578424080dd4fd5a085bf47fe300f5e9",
+ "result": {
+ "engine": "knitr",
+ "markdown": "---\ntitle: \"Day 24\"\ndate: 2023-12-24\nauthor:\n name: https://adventofcode.com/2023/day/24\n url: https://adventofcode.com/2023/day/24\n---\n\n\n\n\n## Setup\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Libraries\nlibrary(tidyverse)\nlibrary(unglue)\n\n# Read input from file\ninput <- read_lines(\"../input/day24.txt\", skip_empty_rows = FALSE)\n```\n:::\n\n\n\n\n## Part 1\n\nConvert text input to structured data:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nbound_min <- 200000000000000\nbound_max <- 400000000000000\n\ndf <- input |> \n unglue_data(\"{px}, {py}, {pz} @ {vx}, {vy}, {vz}\", convert = TRUE) |> \n mutate(id = row_number(), .before = everything())\n\nvecs_2d <- df |> \n transmute(\n id,\n p = pmap(lst(px, py), ~ matrix(c(..1, ..2), ncol = 1)),\n v = pmap(lst(vx, vy), ~ matrix(c(..1, ..2), ncol = 1))\n )\n\nvecs_3d <- df |> \n transmute(\n id,\n p = pmap(lst(px, py, pz), ~ matrix(c(..1, ..2, ..3), ncol = 1)),\n v = pmap(lst(vx, vy, vz), ~ matrix(c(..1, ..2, ..3), ncol = 1))\n )\n```\n:::\n\n\n\n\nThe position $\\vec a$ of a hailstone at any given time $t$ can be written in the format:\n\n$$\\vec vt + \\vec p$$\n\nThe intersection of the paths of any two given hailstones is therefore the point $\\vec a$ where:\n\n$$\n\\vec a = \\vec v_1t_1 + \\vec p_1 = \\vec v_2t_2 = \\vec p_2\n$$\n\nThis can be re-written as the system of equations:\n\n$$\n\\begin{bmatrix}\\vec v_1 &-\\vec v_2\\end{bmatrix}\\begin{bmatrix}t_1\\\\t_2\\end{bmatrix} = \\vec p_2 - \\vec p_1\n$$\n\nSolving this system of equations for each pair of hailstones will give us the values of $t_1$ and $t_2$ that can then be used to compute the coordinates of their intersection, $\\vec a$.\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Combine all hailstones' paths pairwise and solve the system of equations\npairs <- inner_join(\n vecs_2d, \n vecs_2d, \n join_by(x$id < y$id), \n suffix = c(\"1\", \"2\")\n) |> \n mutate(\n A = map2(v1, v2, ~ cbind(..1, -..2)),\n b = map2(p1, p2, ~ ..2 - ..1),\n det = map_dbl(A, det),\n t = pmap(lst(A, b, det), \\(A, b, det) if (det != 0) as.vector(solve(A, b)))\n ) |> \n unnest_wider(t, names_sep = \"\") |> \n \n # Check if each path cross is within the bounding box and forward in time\n mutate(\n intersection = pmap(lst(t1, v1, p1), ~ ..1 * ..2 + ..3),\n in_bounds = map_lgl(intersection, ~ all(between(.x, bound_min, bound_max))),\n future_time = t1 >= 0 & t2 >= 0,\n flag = replace_na(in_bounds & future_time, FALSE)\n )\n\n# Count the number of future-crossing paths:\npairs |> \n pull(flag) |> \n sum()\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[1] 24627\n```\n\n\n:::\n:::\n\n\n\n\n## Part 2\n\nNow our equation has changed. For each hailstone $i$, and for our initial position $\\vec p_*$ and velocity $\\vec v_*$, we have the following relationship, where $t_i$ is the nonzero collision time of our rock and the given hailstone:\n\n$$\n(\\vec v_* - \\vec v_i)t_i = \\vec p_* - \\vec p_i\n$$\n\nSince $t_i$ is a scalar for each $i$, then $\\vec v_i - \\vec v_*$ and $\\vec p_i - \\vec p_*$ are scalar multiples of each other. Thanks to a hint from Reddit user [u/evouga](https://www.reddit.com/r/adventofcode/comments/18pnycy/comment/kepu26z/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button), as these vectors are parallel, their cross product is zero, meaning that for all $i$:\n\n$$\n(\\vec p_* - \\vec p_i) \\times (\\vec v_* - \\vec v_i) = 0\n$$\n\nExpanding this equation by the distributive property of the vector cross product, we get:\n\n$$\n(\\vec p_* \\times \\vec v_*) - (\\vec p_* \\times \\vec v_i) - (\\vec p_i \\times \\vec v_*) + (\\vec p_i \\times \\vec v_i) = 0\n$$\n\nVia [properties of the cross product](https://en.wikipedia.org/wiki/Cross_product#Conversion_to_matrix_multiplication), we can then represent this as:\n\n$$\n(\\vec p_* \\times \\vec v_*) - [\\vec v_i]_\\times^\\intercal \\vec p_* - [\\vec p_i]_\\times \\vec v_* + (\\vec p_i \\times \\vec v_i) = 0\n$$\n\nwhere $[\\vec a]_\\times$ is defined as:\n\n$$\n[\\vec a]_\\times = \\begin{bmatrix}0 & -a_3 & a_2 \\\\ a_3 & 0 & -a_1 \\\\ -a_2 & a_1 & 0\\end{bmatrix}\n$$\n\nWe can now (nearly) re-write this as a system of linear equations:\n\n$$\nA_i\\vec x = \\vec b_i + (\\vec p_* \\times \\vec v_*)\n$$\n\nwhere\n\n$$\nA_i = \\begin{bmatrix}[\\vec v_i]_\\times^\\intercal & [\\vec p_i]_\\times\\end{bmatrix}, \\quad \\vec x = \\begin{bmatrix}\\vec p_* \\\\ \\vec v_*\\end{bmatrix}, \\quad b_i = (\\vec p_i \\times \\vec v_i)\n$$\n\nSince this equation holds for all $i$, we can remove the needless term $(\\vec p_* \\times \\vec v_*)$ and solve for $\\vec x$ by subtracting two of these linear systems of equations from each other (using $i = 1,2$ as below, or any other two values of $i$ whose vectors from part 1 are not parallel):\n\n$$\n(A_1 - A_2)\\vec x = \\vec b_1 - \\vec b_2\n$$\n\nFinally, since we've arrived at a system of 3 equations and 6 unknowns, we append $A$ and $\\vec b$ with an additional pair of equations (using $i = 2,3$, for example) to solve for a final unique result:\n\n$$\n\\begin{bmatrix}A_1 - A_2\\\\A_2 - A_3\\end{bmatrix}\\vec x = \\begin{bmatrix}\\vec b_1 - \\vec b_2\\\\ \\vec b_2 - \\vec b_3\\end{bmatrix}\n$$\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Define a function to compute the skeq symmetric matrix [a]_x\nskewsym <- function(x) {\n matrix(c(0, x[[3]], -x[[2]], -x[[3]], 0, x[[1]], x[[2]], -x[[1]], 0), ncol = 3)\n}\n\n# For the first three vectors in our list, compute their A and b values\nlineqs <- vecs_3d |> \n slice_head(n = 3) |> \n mutate(\n A = map2(p, v, \\(p, v) cbind(t(skewsym(v)), skewsym(p))),\n b = map2(p, v, \\(p, v) pracma::cross(p, v))\n )\n\n# Combine the 3 linear equations into a single system & solve\nA <- rbind(lineqs$A[[1]] - lineqs$A[[2]], lineqs$A[[2]] - lineqs$A[[3]])\nb <- rbind(lineqs$b[[1]] - lineqs$b[[2]], lineqs$b[[2]] - lineqs$b[[3]])\nx <- solve(A, b)\n```\n:::\n\n\n\n\nFinally, add together the three px, py, and pz coordinates for the initial position:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsum(x[1:3]) |> \n format(scientific = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[1] \"527310134398221\"\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/_freeze/2023/R/day25/execute-results/html.json b/_freeze/2023/R/day25/execute-results/html.json
new file mode 100644
index 0000000..f103da1
--- /dev/null
+++ b/_freeze/2023/R/day25/execute-results/html.json
@@ -0,0 +1,17 @@
+{
+ "hash": "4d81263d60da0084b20cf0c536f11188",
+ "result": {
+ "engine": "knitr",
+ "markdown": "---\ntitle: \"Day 25\"\ndate: 2023-12-25\nauthor:\n name: https://adventofcode.com/2023/day/25\n url: https://adventofcode.com/2023/day/25\n---\n\n\n\n\n## Setup\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Libraries\nlibrary(tidyverse)\nlibrary(unglue)\nlibrary(igraph)\n\n# Read input from file\ninput <- read_lines(\"../input/day25.txt\", skip_empty_rows = FALSE)\n```\n:::\n\n\n\n\n## Part 1\n\nConvert text input to a graph:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nwires <- input |> \n str_split(\":? \") |> \n unlist() |> \n unique()\n\nedges <- input |> \n unglue_data(\"{name}: {conn}\") |> \n mutate(conn = str_split(conn, \" \")) |> \n unnest_longer(conn) |> \n mutate(across(c(name, conn), ~ match(.x, wires))) |> \n pmap(\\(name, conn) c(name, conn)) |> \n unlist()\n\ng <- make_graph(edges, directed = FALSE)\n```\n:::\n\n\n\n\nCompute the betweenness of each edge and pull the three with the maximum values:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nscores <- edge_betweenness(g)\nidx <- scores |> \n sort(decreasing = TRUE) |> \n head(3) |> \n match(scores)\n```\n:::\n\n\n\n\nPlot for visual confirmation:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nedge_colors <- E(g) |> \n as.numeric() |> \n case_match(idx ~ \"blue\", .default = \"grey\")\n\nplot(g, vertex.size = 4, vertex.label = NA, edge.color = edge_colors)\n```\n\n::: {.cell-output-display}\n![](day25_files/figure-html/unnamed-chunk-3-1.png){width=672}\n:::\n:::\n\n\n\n\nRemove the selected vertices from the graph, then calculate the product of the size of its two disconnected groups:\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\ng |> \n delete_edges(idx) |> \n components() |> \n pluck(\"csize\") |> \n prod()\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[1] 552695\n```\n\n\n:::\n:::\n",
+ "supporting": [
+ "day25_files"
+ ],
+ "filters": [
+ "rmarkdown/pagebreak.lua"
+ ],
+ "includes": {},
+ "engineDependencies": {},
+ "preserve": {},
+ "postProcess": true
+ }
+}
\ No newline at end of file
diff --git a/_freeze/2023/R/day25/figure-html/unnamed-chunk-3-1.png b/_freeze/2023/R/day25/figure-html/unnamed-chunk-3-1.png
new file mode 100644
index 0000000..08b9d34
Binary files /dev/null and b/_freeze/2023/R/day25/figure-html/unnamed-chunk-3-1.png differ
diff --git a/docs/2022/R/day01.html b/docs/2022/R/day01.html
index 395fd0e..c6cb4df 100644
--- a/docs/2022/R/day01.html
+++ b/docs/2022/R/day01.html
@@ -67,7 +67,7 @@
-
+
@@ -436,6 +436,24 @@
Day 1
+
+
+
+
@@ -1122,8 +1140,8 @@ Part 2
-
diff --git a/docs/2022/R/day02.html b/docs/2022/R/day02.html
index 789f017..4805be3 100644
--- a/docs/2022/R/day02.html
+++ b/docs/2022/R/day02.html
@@ -436,6 +436,24 @@
Day 2
+
+
+
+
diff --git a/docs/2022/R/day03.html b/docs/2022/R/day03.html
index 8a06791..6a749f6 100644
--- a/docs/2022/R/day03.html
+++ b/docs/2022/R/day03.html
@@ -436,6 +436,24 @@ Day 3
+
+
+
+
diff --git a/docs/2022/R/day04.html b/docs/2022/R/day04.html
index 2750531..04abcf4 100644
--- a/docs/2022/R/day04.html
+++ b/docs/2022/R/day04.html
@@ -436,6 +436,24 @@ Day 4
+
+
+
+
diff --git a/docs/2022/R/day05.html b/docs/2022/R/day05.html
index 216008d..6205e50 100644
--- a/docs/2022/R/day05.html
+++ b/docs/2022/R/day05.html
@@ -436,6 +436,24 @@ Day 5
+
+
+
+
diff --git a/docs/2022/R/day06.html b/docs/2022/R/day06.html
index 19ab8e5..8751e26 100644
--- a/docs/2022/R/day06.html
+++ b/docs/2022/R/day06.html
@@ -436,6 +436,24 @@ Day 6
+
+
+
+
diff --git a/docs/2022/R/day07.html b/docs/2022/R/day07.html
index 91560fc..8c98a19 100644
--- a/docs/2022/R/day07.html
+++ b/docs/2022/R/day07.html
@@ -436,6 +436,24 @@ Day 7
+
+
+
+
diff --git a/docs/2022/R/day08.html b/docs/2022/R/day08.html
index d89733e..8a5013a 100644
--- a/docs/2022/R/day08.html
+++ b/docs/2022/R/day08.html
@@ -436,6 +436,24 @@ Day 8
+
+
+
+
diff --git a/docs/2022/R/day09.html b/docs/2022/R/day09.html
index 6e14e28..cc98432 100644
--- a/docs/2022/R/day09.html
+++ b/docs/2022/R/day09.html
@@ -436,6 +436,24 @@ Day 9
+
+
+
+
diff --git a/docs/2022/R/day10.html b/docs/2022/R/day10.html
index d6f702c..f3b3e55 100644
--- a/docs/2022/R/day10.html
+++ b/docs/2022/R/day10.html
@@ -436,6 +436,24 @@ Day 10
+
+
+
+
diff --git a/docs/2022/R/day11.html b/docs/2022/R/day11.html
index b3f2e03..844c0eb 100644
--- a/docs/2022/R/day11.html
+++ b/docs/2022/R/day11.html
@@ -436,6 +436,24 @@ Day 11
+
+
+
+
diff --git a/docs/2022/R/day12.html b/docs/2022/R/day12.html
index 09ae068..a550f74 100644
--- a/docs/2022/R/day12.html
+++ b/docs/2022/R/day12.html
@@ -436,6 +436,24 @@ Day 12
+
+
+
+
diff --git a/docs/2022/R/day13.html b/docs/2022/R/day13.html
index 63c2c3b..655dfa1 100644
--- a/docs/2022/R/day13.html
+++ b/docs/2022/R/day13.html
@@ -436,6 +436,24 @@ Day 13
+
+
+
+
diff --git a/docs/2022/R/day14.html b/docs/2022/R/day14.html
index 9c8427f..daad4dc 100644
--- a/docs/2022/R/day14.html
+++ b/docs/2022/R/day14.html
@@ -436,6 +436,24 @@ Day 14
+
+
+
+
diff --git a/docs/2022/R/day15.html b/docs/2022/R/day15.html
index c260d0f..98c00f7 100644
--- a/docs/2022/R/day15.html
+++ b/docs/2022/R/day15.html
@@ -436,6 +436,24 @@ Day 15
+
+
+
+
diff --git a/docs/2022/R/day16.html b/docs/2022/R/day16.html
index ea076f5..e73414a 100644
--- a/docs/2022/R/day16.html
+++ b/docs/2022/R/day16.html
@@ -436,6 +436,24 @@ Day 16
+
+
+
+
diff --git a/docs/2022/R/day17.html b/docs/2022/R/day17.html
index bea630d..956815c 100644
--- a/docs/2022/R/day17.html
+++ b/docs/2022/R/day17.html
@@ -436,6 +436,24 @@ Day 17
+
+
+
+
diff --git a/docs/2022/R/day18.html b/docs/2022/R/day18.html
index ddc18c8..5077d2c 100644
--- a/docs/2022/R/day18.html
+++ b/docs/2022/R/day18.html
@@ -436,6 +436,24 @@ Day 18
+
+
+
+
diff --git a/docs/2022/R/day19.html b/docs/2022/R/day19.html
index 99a1ddb..d213415 100644
--- a/docs/2022/R/day19.html
+++ b/docs/2022/R/day19.html
@@ -436,6 +436,24 @@ Day 19
+
+
+
+
diff --git a/docs/2022/R/day20.html b/docs/2022/R/day20.html
index 6b7318c..99f1c25 100644
--- a/docs/2022/R/day20.html
+++ b/docs/2022/R/day20.html
@@ -436,6 +436,24 @@ Day 20
+
+
+
+
diff --git a/docs/2022/R/day21.html b/docs/2022/R/day21.html
index 8c60e59..4831895 100644
--- a/docs/2022/R/day21.html
+++ b/docs/2022/R/day21.html
@@ -436,6 +436,24 @@ Day 21
+
+
+
+
diff --git a/docs/2022/R/day22.html b/docs/2022/R/day22.html
index 24f5bf3..575e085 100644
--- a/docs/2022/R/day22.html
+++ b/docs/2022/R/day22.html
@@ -436,6 +436,24 @@ Day 22
+
+
+
+
diff --git a/docs/2022/R/day23.html b/docs/2022/R/day23.html
index 24d1576..dc2d9ee 100644
--- a/docs/2022/R/day23.html
+++ b/docs/2022/R/day23.html
@@ -436,6 +436,24 @@ Day 23
+
+
+
+
diff --git a/docs/2022/R/day24.html b/docs/2022/R/day24.html
index b547636..aab3be7 100644
--- a/docs/2022/R/day24.html
+++ b/docs/2022/R/day24.html
@@ -436,6 +436,24 @@ Day 24
+
+
+
+
diff --git a/docs/2022/R/day25.html b/docs/2022/R/day25.html
index c6a4508..8f9f07a 100644
--- a/docs/2022/R/day25.html
+++ b/docs/2022/R/day25.html
@@ -435,6 +435,24 @@ Day 25
+
+
+
+
diff --git a/docs/2023/R/day01.html b/docs/2023/R/day01.html
index 6f941b0..94fb6ca 100644
--- a/docs/2023/R/day01.html
+++ b/docs/2023/R/day01.html
@@ -436,6 +436,24 @@ Day 1
+
+
+
+
diff --git a/docs/2023/R/day02.html b/docs/2023/R/day02.html
index b67d547..5d49c9d 100644
--- a/docs/2023/R/day02.html
+++ b/docs/2023/R/day02.html
@@ -436,6 +436,24 @@ Day 2
+
+
+
+
diff --git a/docs/2023/R/day03.html b/docs/2023/R/day03.html
index 7fc26a0..f0b906c 100644
--- a/docs/2023/R/day03.html
+++ b/docs/2023/R/day03.html
@@ -436,6 +436,24 @@ Day 3
+
+
+
+
diff --git a/docs/2023/R/day04.html b/docs/2023/R/day04.html
index 810449a..380447e 100644
--- a/docs/2023/R/day04.html
+++ b/docs/2023/R/day04.html
@@ -436,6 +436,24 @@ Day 4
+
+
+
+
diff --git a/docs/2023/R/day05.html b/docs/2023/R/day05.html
index adf4f55..995050a 100644
--- a/docs/2023/R/day05.html
+++ b/docs/2023/R/day05.html
@@ -436,6 +436,24 @@ Day 5
+
+
+
+
diff --git a/docs/2023/R/day06.html b/docs/2023/R/day06.html
index a03bfa9..59bc195 100644
--- a/docs/2023/R/day06.html
+++ b/docs/2023/R/day06.html
@@ -436,6 +436,24 @@ Day 6
+
+
+
+
diff --git a/docs/2023/R/day07.html b/docs/2023/R/day07.html
index 67c79cb..22afa27 100644
--- a/docs/2023/R/day07.html
+++ b/docs/2023/R/day07.html
@@ -436,6 +436,24 @@ Day 7
+
+
+
+
diff --git a/docs/2023/R/day08.html b/docs/2023/R/day08.html
index 637c986..578bc28 100644
--- a/docs/2023/R/day08.html
+++ b/docs/2023/R/day08.html
@@ -436,6 +436,24 @@ Day 8
+
+
+
+
diff --git a/docs/2023/R/day09.html b/docs/2023/R/day09.html
index 49c35a3..382e036 100644
--- a/docs/2023/R/day09.html
+++ b/docs/2023/R/day09.html
@@ -436,6 +436,24 @@ Day 9
+
+
+
+
diff --git a/docs/2023/R/day10.html b/docs/2023/R/day10.html
index a9570ee..603ac44 100644
--- a/docs/2023/R/day10.html
+++ b/docs/2023/R/day10.html
@@ -436,6 +436,24 @@ Day 10
+
+
+
+
diff --git a/docs/2023/R/day11.html b/docs/2023/R/day11.html
index 0c6a45d..8e60d82 100644
--- a/docs/2023/R/day11.html
+++ b/docs/2023/R/day11.html
@@ -436,6 +436,24 @@ Day 11
+
+
+
+
diff --git a/docs/2023/R/day12.html b/docs/2023/R/day12.html
index b5da48f..edca3d1 100644
--- a/docs/2023/R/day12.html
+++ b/docs/2023/R/day12.html
@@ -436,6 +436,24 @@ Day 12
+
+
+
+
diff --git a/docs/2023/R/day13.html b/docs/2023/R/day13.html
index e848933..13b9dc0 100644
--- a/docs/2023/R/day13.html
+++ b/docs/2023/R/day13.html
@@ -436,6 +436,24 @@ Day 13
+
+
+
+
diff --git a/docs/2023/R/day14.html b/docs/2023/R/day14.html
index f285614..3888417 100644
--- a/docs/2023/R/day14.html
+++ b/docs/2023/R/day14.html
@@ -436,6 +436,24 @@ Day 14
+
+
+
+
diff --git a/docs/2023/R/day15.html b/docs/2023/R/day15.html
index a41469c..1cd652e 100644
--- a/docs/2023/R/day15.html
+++ b/docs/2023/R/day15.html
@@ -436,6 +436,24 @@ Day 15
+
+
+
+
diff --git a/docs/2023/R/day16.html b/docs/2023/R/day16.html
index 14985b9..7f0d12e 100644
--- a/docs/2023/R/day16.html
+++ b/docs/2023/R/day16.html
@@ -436,6 +436,24 @@ Day 16
+
+
+
+
diff --git a/docs/2023/R/day17.html b/docs/2023/R/day17.html
index 02d7862..f1abad9 100644
--- a/docs/2023/R/day17.html
+++ b/docs/2023/R/day17.html
@@ -436,6 +436,24 @@ Day 17
+
+
+
+
diff --git a/docs/2023/R/day18.html b/docs/2023/R/day18.html
index c616530..2d1bf49 100644
--- a/docs/2023/R/day18.html
+++ b/docs/2023/R/day18.html
@@ -436,6 +436,24 @@ Day 18
+
+
+
+
diff --git a/docs/2023/R/day19.html b/docs/2023/R/day19.html
index 24a3b2c..ba41db2 100644
--- a/docs/2023/R/day19.html
+++ b/docs/2023/R/day19.html
@@ -436,6 +436,24 @@ Day 19
+
+
+
+
diff --git a/docs/2023/R/day20.html b/docs/2023/R/day20.html
index 0999001..5ec7b4b 100644
--- a/docs/2023/R/day20.html
+++ b/docs/2023/R/day20.html
@@ -436,6 +436,24 @@ Day 20
+
+
+
+
diff --git a/docs/2023/R/day21.html b/docs/2023/R/day21.html
index 6818b50..e20d09f 100644
--- a/docs/2023/R/day21.html
+++ b/docs/2023/R/day21.html
@@ -436,6 +436,24 @@ Day 21
+
+
+
+
diff --git a/docs/2023/R/day22.html b/docs/2023/R/day22.html
index f9664ce..b8e098c 100644
--- a/docs/2023/R/day22.html
+++ b/docs/2023/R/day22.html
@@ -66,7 +66,7 @@
-
+
@@ -436,6 +436,24 @@ Day 22
+
+
+
+
@@ -1248,8 +1266,8 @@ Part 2
-
diff --git a/docs/2023/R/day23.html b/docs/2023/R/day23.html
new file mode 100644
index 0000000..7c2a1a5
--- /dev/null
+++ b/docs/2023/R/day23.html
@@ -0,0 +1,1271 @@
+
+
+
+
+
+
+
+
+
+
+
+Day 23 – Advent of Code: Worked Solutions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Setup
+
+
# Libraries
+library (tidyverse)
+library (igraph)
+
+# Read input from file
+ input <- read_lines ("../input/day23.txt" , skip_empty_rows = FALSE )
+
+
+
+Part 1
+Convert text input to a directed graph:
+
+
# Convert to a dataframe with IDs and coordinates per cell
+ df <- input |>
+ str_split ("" ) |>
+ enframe (name = "row" ) |>
+ unnest_longer (value, indices_to = "col" ) |>
+ mutate (id = row_number ()) |>
+ filter (value != '#' ) |>
+ relocate (id, value, row, col)
+
+# Compute the list of directed edges between cells
+ edges <- df |>
+ mutate (
+ row_n = row - 1 ,
+ row_s = row + 1 ,
+ col_w = col - 1 ,
+ col_e = col + 1
+ ) |>
+ left_join (df, join_by (x$ row_n == y$ row, col), suffix = c ("" , "_n" )) |>
+ left_join (df, join_by (x$ row_s == y$ row, col), suffix = c ("" , "_s" )) |>
+ left_join (df, join_by (x$ col_w == y$ col, row), suffix = c ("" , "_w" )) |>
+ left_join (df, join_by (x$ col_e == y$ col, row), suffix = c ("" , "_e" )) |>
+ select (- starts_with (c ("row" , "col" , "value_" ))) |>
+ pivot_longer (
+ starts_with ("id_" ),
+ names_to = "dir" ,
+ values_to = "neighbor" ,
+ names_prefix = "id_"
+ ) |>
+
+ # For slope tiles, remove any non-downhill neighbors
+ filter (
+ (value == "." & ! is.na (neighbor)) |
+ (value == "^" & dir == "n" ) |
+ (value == "v" & dir == "s" ) |
+ (value == "<" & dir == "w" ) |
+ (value == ">" & dir == "e" )
+ ) |>
+ pmap (\(id, neighbor, ...) c (id, neighbor)) |>
+ unlist ()
+
+# Convert to a graph
+ g <- make_graph (edges)
+
+Find the longest possible path from the start point to the end point:
+
+
source <- min (df$ id)
+ target <- max (df$ id)
+
+ max_hike <- function (g, from = source, to = target) {
+ all_simple_paths (g, from, to) |>
+ map_dbl (~ length (.x) - 1 ) |>
+ sort (decreasing = TRUE ) |>
+ max ()
+ }
+
+max_hike (g)
+
+
+
+
+Part 2
+Convert to an undirected graph to remove the slope constraint:
+
+
g <- as_undirected (g)
+V (g)$ name <- V (g)
+
+The graph is too large to simply run the hike length function again – an overflow results.
+Instead, we notice that the input maze consists of relatively few intersections. Most of the maze input is simple corridors with no path decisions. We can reduce the graph complexity/size by trimming away our non-choice verftices and converting the length of those paths to an edge weight.
+
+
v_zero_edges <- names (which (degree (g) == 0 ))
+ v_two_edges <- names (which (degree (g) == 2 ))
+ v_nontwo_edges <- names (which (degree (g) != 2 ))
+
+# Extract all corridor vertices
+ g_corridors <- delete_vertices (g, v_nontwo_edges)
+ corridors <- components (g_corridors)
+
+# Determine which edges to add to replace the corridors and their weight
+ new_weights <- corridors$ csize + 1
+ new_edges <- corridors$ membership |>
+ keep_at (names (which (degree (g_corridors) == 1 ))) |>
+ enframe (name = "vtx" , value = "group" ) |>
+ mutate (vtx = map_chr (vtx, ~ setdiff (names (neighbors (g, .x)), v_two_edges))) |>
+ summarize (edge = list (vtx), .by = group) |>
+ arrange (group) |>
+ pull (edge)
+
+# Create a new graph without the corridor vertices, then add its new edges
+ g_new <- reduce2 (
+ .x = new_edges,
+ .y = new_weights,
+ .f = \(g, e, w) add_edges (g, e, weight = w),
+ .init = delete_vertices (g, c (v_zero_edges, v_two_edges))
+ )
+
+View a plot of the resulting simplified graph:
+
+
vtx_labels <- g_new |>
+ V () |>
+ names () |>
+ case_match (
+ as.character (source) ~ "S" ,
+ as.character (target) ~ "E" ,
+ .default = ""
+ )
+
+plot (
+ g_new,
+ vertex.size = 8 ,
+ vertex.label = vtx_labels,
+ edge.label = E (g_new)$ weight
+ )
+
+
+
+
+
+
+
+
+Compute all paths from the start to the end using our smaller graph:
+
+
all_paths <- g_new |>
+ all_simple_paths (as.character (source), as.character (target))
+
+Using the edge weights of our graph, compute the total length of each path and select the longest:
+
+
all_paths |>
+ map (
+ ~ .x |>
+ as_ids () |>
+ rep (each = 2 ) |>
+ head (- 1 ) |>
+ tail (- 1 ) |>
+ get_edge_ids (graph = g_new)
+ ) |>
+ map (~ E (g_new)$ weight[.x]) |>
+ map_dbl (sum) |>
+ max ()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/2023/R/day23_files/figure-html/unnamed-chunk-5-1.png b/docs/2023/R/day23_files/figure-html/unnamed-chunk-5-1.png
new file mode 100644
index 0000000..3401e27
Binary files /dev/null and b/docs/2023/R/day23_files/figure-html/unnamed-chunk-5-1.png differ
diff --git a/docs/2023/R/day24.html b/docs/2023/R/day24.html
new file mode 100644
index 0000000..e6ee7fd
--- /dev/null
+++ b/docs/2023/R/day24.html
@@ -0,0 +1,1285 @@
+
+
+
+
+
+
+
+
+
+
+
+Day 24 – Advent of Code: Worked Solutions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Setup
+
+
# Libraries
+library (tidyverse)
+library (unglue)
+
+# Read input from file
+ input <- read_lines ("../input/day24.txt" , skip_empty_rows = FALSE )
+
+
+
+Part 1
+Convert text input to structured data:
+
+
bound_min <- 200000000000000
+ bound_max <- 400000000000000
+
+ df <- input |>
+ unglue_data ("{px}, {py}, {pz} @ {vx}, {vy}, {vz}" , convert = TRUE ) |>
+ mutate (id = row_number (), .before = everything ())
+
+ vecs_2d <- df |>
+ transmute (
+ id,
+ p = pmap (lst (px, py), ~ matrix (c (..1 , ..2 ), ncol = 1 )),
+ v = pmap (lst (vx, vy), ~ matrix (c (..1 , ..2 ), ncol = 1 ))
+ )
+
+ vecs_3d <- df |>
+ transmute (
+ id,
+ p = pmap (lst (px, py, pz), ~ matrix (c (..1 , ..2 , ..3 ), ncol = 1 )),
+ v = pmap (lst (vx, vy, vz), ~ matrix (c (..1 , ..2 , ..3 ), ncol = 1 ))
+ )
+
+The position \(\vec a\) of a hailstone at any given time \(t\) can be written in the format:
+\[\vec vt + \vec p\]
+The intersection of the paths of any two given hailstones is therefore the point \(\vec a\) where:
+\[
+\vec a = \vec v_1t_1 + \vec p_1 = \vec v_2t_2 = \vec p_2
+\]
+This can be re-written as the system of equations:
+\[
+\begin{bmatrix}\vec v_1 &-\vec v_2\end{bmatrix}\begin{bmatrix}t_1\\t_2\end{bmatrix} = \vec p_2 - \vec p_1
+\]
+Solving this system of equations for each pair of hailstones will give us the values of \(t_1\) and \(t_2\) that can then be used to compute the coordinates of their intersection, \(\vec a\) .
+
+
# Combine all hailstones' paths pairwise and solve the system of equations
+ pairs <- inner_join (
+ vecs_2d,
+ vecs_2d,
+ join_by (x$ id < y$ id),
+ suffix = c ("1" , "2" )
+ ) |>
+ mutate (
+ A = map2 (v1, v2, ~ cbind (..1 , - ..2 )),
+ b = map2 (p1, p2, ~ ..2 - ..1 ),
+ det = map_dbl (A, det),
+ t = pmap (lst (A, b, det), \(A, b, det) if (det != 0 ) as.vector (solve (A, b)))
+ ) |>
+ unnest_wider (t, names_sep = "" ) |>
+
+ # Check if each path cross is within the bounding box and forward in time
+ mutate (
+ intersection = pmap (lst (t1, v1, p1), ~ ..1 * ..2 + ..3 ),
+ in_bounds = map_lgl (intersection, ~ all (between (.x, bound_min, bound_max))),
+ future_time = t1 >= 0 & t2 >= 0 ,
+ flag = replace_na (in_bounds & future_time, FALSE )
+ )
+
+# Count the number of future-crossing paths:
+ pairs |>
+ pull (flag) |>
+ sum ()
+
+
+
+
+Part 2
+Now our equation has changed. For each hailstone \(i\) , and for our initial position \(\vec p_*\) and velocity \(\vec v_*\) , we have the following relationship, where \(t_i\) is the nonzero collision time of our rock and the given hailstone:
+\[
+(\vec v_* - \vec v_i)t_i = \vec p_* - \vec p_i
+\]
+Since \(t_i\) is a scalar for each \(i\) , then \(\vec v_i - \vec v_*\) and \(\vec p_i - \vec p_*\) are scalar multiples of each other. Thanks to a hint from Reddit user u/evouga , as these vectors are parallel, their cross product is zero, meaning that for all \(i\) :
+\[
+(\vec p_* - \vec p_i) \times (\vec v_* - \vec v_i) = 0
+\]
+Expanding this equation by the distributive property of the vector cross product, we get:
+\[
+(\vec p_* \times \vec v_*) - (\vec p_* \times \vec v_i) - (\vec p_i \times \vec v_*) + (\vec p_i \times \vec v_i) = 0
+\]
+Via properties of the cross product , we can then represent this as:
+\[
+(\vec p_* \times \vec v_*) - [\vec v_i]_\times^\intercal \vec p_* - [\vec p_i]_\times \vec v_* + (\vec p_i \times \vec v_i) = 0
+\]
+where \([\vec a]_\times\) is defined as:
+\[
+[\vec a]_\times = \begin{bmatrix}0 & -a_3 & a_2 \\ a_3 & 0 & -a_1 \\ -a_2 & a_1 & 0\end{bmatrix}
+\]
+We can now (nearly) re-write this as a system of linear equations:
+\[
+A_i\vec x = \vec b_i + (\vec p_* \times \vec v_*)
+\]
+where
+\[
+A_i = \begin{bmatrix}[\vec v_i]_\times^\intercal & [\vec p_i]_\times\end{bmatrix}, \quad \vec x = \begin{bmatrix}\vec p_* \\ \vec v_*\end{bmatrix}, \quad b_i = (\vec p_i \times \vec v_i)
+\]
+Since this equation holds for all \(i\) , we can remove the needless term \((\vec p_* \times \vec v_*)\) and solve for \(\vec x\) by subtracting two of these linear systems of equations from each other (using \(i = 1,2\) as below, or any other two values of \(i\) whose vectors from part 1 are not parallel):
+\[
+(A_1 - A_2)\vec x = \vec b_1 - \vec b_2
+\]
+Finally, since we’ve arrived at a system of 3 equations and 6 unknowns, we append \(A\) and \(\vec b\) with an additional pair of equations (using \(i = 2,3\) , for example) to solve for a final unique result:
+\[
+\begin{bmatrix}A_1 - A_2\\A_2 - A_3\end{bmatrix}\vec x = \begin{bmatrix}\vec b_1 - \vec b_2\\ \vec b_2 - \vec b_3\end{bmatrix}
+\]
+
+
# Define a function to compute the skeq symmetric matrix [a]_x
+ skewsym <- function (x) {
+ matrix (c (0 , x[[3 ]], - x[[2 ]], - x[[3 ]], 0 , x[[1 ]], x[[2 ]], - x[[1 ]], 0 ), ncol = 3 )
+ }
+
+# For the first three vectors in our list, compute their A and b values
+ lineqs <- vecs_3d |>
+ slice_head (n = 3 ) |>
+ mutate (
+ A = map2 (p, v, \(p, v) cbind (t (skewsym (v)), skewsym (p))),
+ b = map2 (p, v, \(p, v) pracma:: cross (p, v))
+ )
+
+# Combine the 3 linear equations into a single system & solve
+ A <- rbind (lineqs$ A[[1 ]] - lineqs$ A[[2 ]], lineqs$ A[[2 ]] - lineqs$ A[[3 ]])
+ b <- rbind (lineqs$ b[[1 ]] - lineqs$ b[[2 ]], lineqs$ b[[2 ]] - lineqs$ b[[3 ]])
+ x <- solve (A, b)
+
+Finally, add together the three px, py, and pz coordinates for the initial position:
+
+
sum (x[1 : 3 ]) |>
+ format (scientific = FALSE )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/2023/R/day25.html b/docs/2023/R/day25.html
new file mode 100644
index 0000000..bf69e11
--- /dev/null
+++ b/docs/2023/R/day25.html
@@ -0,0 +1,1175 @@
+
+
+
+
+
+
+
+
+
+
+
+Day 25 – Advent of Code: Worked Solutions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Setup
+
+
# Libraries
+library (tidyverse)
+library (unglue)
+library (igraph)
+
+# Read input from file
+ input <- read_lines ("../input/day25.txt" , skip_empty_rows = FALSE )
+
+
+
+Part 1
+Convert text input to a graph:
+
+
wires <- input |>
+ str_split (":? " ) |>
+ unlist () |>
+ unique ()
+
+ edges <- input |>
+ unglue_data ("{name}: {conn}" ) |>
+ mutate (conn = str_split (conn, " " )) |>
+ unnest_longer (conn) |>
+ mutate (across (c (name, conn), ~ match (.x, wires))) |>
+ pmap (\(name, conn) c (name, conn)) |>
+ unlist ()
+
+ g <- make_graph (edges, directed = FALSE )
+
+Compute the betweenness of each edge and pull the three with the maximum values:
+
+
scores <- edge_betweenness (g)
+ idx <- scores |>
+ sort (decreasing = TRUE ) |>
+ head (3 ) |>
+ match (scores)
+
+Plot for visual confirmation:
+
+
edge_colors <- E (g) |>
+ as.numeric () |>
+ case_match (idx ~ "blue" , .default = "grey" )
+
+plot (g, vertex.size = 4 , vertex.label = NA , edge.color = edge_colors)
+
+
+
+
+
+
+
+
+Remove the selected vertices from the graph, then calculate the product of the size of its two disconnected groups:
+
+
g |>
+ delete_edges (idx) |>
+ components () |>
+ pluck ("csize" ) |>
+ prod ()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/2023/R/day25_files/figure-html/unnamed-chunk-3-1.png b/docs/2023/R/day25_files/figure-html/unnamed-chunk-3-1.png
new file mode 100644
index 0000000..08b9d34
Binary files /dev/null and b/docs/2023/R/day25_files/figure-html/unnamed-chunk-3-1.png differ
diff --git a/docs/2024/R/day01.html b/docs/2024/R/day01.html
index 02dd1aa..ef3d1f5 100644
--- a/docs/2024/R/day01.html
+++ b/docs/2024/R/day01.html
@@ -435,6 +435,24 @@ Day 1
+
+
+
+
diff --git a/docs/2024/R/day02.html b/docs/2024/R/day02.html
index 35b5f08..7487528 100644
--- a/docs/2024/R/day02.html
+++ b/docs/2024/R/day02.html
@@ -436,6 +436,24 @@ Day 2
+
+
+
+
diff --git a/docs/2024/R/day03.html b/docs/2024/R/day03.html
index 347c407..53a520e 100644
--- a/docs/2024/R/day03.html
+++ b/docs/2024/R/day03.html
@@ -436,6 +436,24 @@ Day 3
+
+
+
+
diff --git a/docs/2024/R/day04.html b/docs/2024/R/day04.html
index c6bd841..c1a715f 100644
--- a/docs/2024/R/day04.html
+++ b/docs/2024/R/day04.html
@@ -436,6 +436,24 @@ Day 4
+
+
+
+
diff --git a/docs/2024/R/day05.html b/docs/2024/R/day05.html
index b28b95d..ddd9e04 100644
--- a/docs/2024/R/day05.html
+++ b/docs/2024/R/day05.html
@@ -436,6 +436,24 @@ Day 5
+
+
+
+
diff --git a/docs/2024/R/day06.html b/docs/2024/R/day06.html
index 9433a72..8154a37 100644
--- a/docs/2024/R/day06.html
+++ b/docs/2024/R/day06.html
@@ -436,6 +436,24 @@ Day 6
+
+
+
+
diff --git a/docs/2024/R/day07.html b/docs/2024/R/day07.html
index d86aa19..dc6f2af 100644
--- a/docs/2024/R/day07.html
+++ b/docs/2024/R/day07.html
@@ -436,6 +436,24 @@ Day 7
+
+
+
+
diff --git a/docs/2024/R/day08.html b/docs/2024/R/day08.html
index 078d5a0..7376cab 100644
--- a/docs/2024/R/day08.html
+++ b/docs/2024/R/day08.html
@@ -436,6 +436,24 @@ Day 8
+
+
+
+
diff --git a/docs/2024/R/day09.html b/docs/2024/R/day09.html
index d379095..f1a2cab 100644
--- a/docs/2024/R/day09.html
+++ b/docs/2024/R/day09.html
@@ -436,6 +436,24 @@ Day 9
+
+
+
+
diff --git a/docs/2024/R/day10.html b/docs/2024/R/day10.html
index de6e194..5947c7c 100644
--- a/docs/2024/R/day10.html
+++ b/docs/2024/R/day10.html
@@ -436,6 +436,24 @@ Day 10
+
+
+
+
diff --git a/docs/2024/R/day11.html b/docs/2024/R/day11.html
index f202485..abac1dc 100644
--- a/docs/2024/R/day11.html
+++ b/docs/2024/R/day11.html
@@ -436,6 +436,24 @@ Day 11
+
+
+
+
diff --git a/docs/2024/R/day12.html b/docs/2024/R/day12.html
index 4a79601..1a13d16 100644
--- a/docs/2024/R/day12.html
+++ b/docs/2024/R/day12.html
@@ -436,6 +436,24 @@ Day 12
+
+
+
+
diff --git a/docs/2024/R/day13.html b/docs/2024/R/day13.html
index d6cdc94..ac36e46 100644
--- a/docs/2024/R/day13.html
+++ b/docs/2024/R/day13.html
@@ -436,6 +436,24 @@ Day 13
+
+
+
+
diff --git a/docs/2024/R/day14.html b/docs/2024/R/day14.html
index bb2c744..097c067 100644
--- a/docs/2024/R/day14.html
+++ b/docs/2024/R/day14.html
@@ -436,6 +436,24 @@ Day 14
+
+
+
+
diff --git a/docs/2024/R/day15.html b/docs/2024/R/day15.html
index b8b8ff0..66da5a0 100644
--- a/docs/2024/R/day15.html
+++ b/docs/2024/R/day15.html
@@ -436,6 +436,24 @@ Day 15
+
+
+
+
diff --git a/docs/2024/R/day16.html b/docs/2024/R/day16.html
index a6833ce..4ccc9fe 100644
--- a/docs/2024/R/day16.html
+++ b/docs/2024/R/day16.html
@@ -436,6 +436,24 @@ Day 16
+
+
+
+
diff --git a/docs/2024/R/day17.html b/docs/2024/R/day17.html
index ef167fb..7d6d8a8 100644
--- a/docs/2024/R/day17.html
+++ b/docs/2024/R/day17.html
@@ -436,6 +436,24 @@ Day 17
+
+
+
+
diff --git a/docs/2024/R/day18.html b/docs/2024/R/day18.html
index 3b4c2f6..a03605f 100644
--- a/docs/2024/R/day18.html
+++ b/docs/2024/R/day18.html
@@ -436,6 +436,24 @@ Day 18
+
+
+
+
diff --git a/docs/2024/R/day19.html b/docs/2024/R/day19.html
index 2584555..8e634bd 100644
--- a/docs/2024/R/day19.html
+++ b/docs/2024/R/day19.html
@@ -436,6 +436,24 @@ Day 19
+
+
+
+
diff --git a/docs/2024/R/day20.html b/docs/2024/R/day20.html
index e634865..b179f1d 100644
--- a/docs/2024/R/day20.html
+++ b/docs/2024/R/day20.html
@@ -436,6 +436,24 @@ Day 20
+
+
+
+
diff --git a/docs/2024/R/day21.html b/docs/2024/R/day21.html
index cae221e..8714e3c 100644
--- a/docs/2024/R/day21.html
+++ b/docs/2024/R/day21.html
@@ -436,6 +436,24 @@ Day 21
+
+
+
+
diff --git a/docs/2024/R/day22.html b/docs/2024/R/day22.html
index 94002f2..22f8586 100644
--- a/docs/2024/R/day22.html
+++ b/docs/2024/R/day22.html
@@ -436,6 +436,24 @@ Day 22
+
+
+
+
diff --git a/docs/2024/R/day23.html b/docs/2024/R/day23.html
index 464df29..0706326 100644
--- a/docs/2024/R/day23.html
+++ b/docs/2024/R/day23.html
@@ -436,6 +436,24 @@ Day 23
+
+
+
+
diff --git a/docs/2024/R/day24.html b/docs/2024/R/day24.html
index c31fa5e..408aa38 100644
--- a/docs/2024/R/day24.html
+++ b/docs/2024/R/day24.html
@@ -436,6 +436,24 @@ Day 24
+
+
+
+
diff --git a/docs/2024/R/day25.html b/docs/2024/R/day25.html
index e5ed8f1..581668d 100644
--- a/docs/2024/R/day25.html
+++ b/docs/2024/R/day25.html
@@ -436,6 +436,24 @@ Day 25
+
+
+
+
diff --git a/docs/index.html b/docs/index.html
index 16efcb8..ed4240b 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -7,7 +7,7 @@
-
+
Advent of Code: Worked Solutions