library(tidyverse)
library(here)
library(rlang)
Part 1
This is a fairly straightforward puzzle. The trickiest part of this puzzle is writing out the regex to match the proper conditions, based on the arragnements.
The idea of this puzzle is that we are given a set of conditions of ‘hot springs’, where . are considered ‘working’ and # are considered ‘broken’. We area also given ? which means it can either be working or broken. We are also given a set of arragnements, or ‘sets’ of broken hot springs. For row #1, the arragements of 4,4 indicates there are 2 sets of 4 consecutive broken hot springs, separated by at elast 1 working hot spring. The goal is to determine the number of possible arrangements of hot springs that satisfy the given conditions.
As always, lets start off with reading in the puzzle input.
<- read_lines(
data here('posts', 'aoc-2023-d12', 'puzzle-input.txt')
)
<- data |>
data as_tibble() |>
separate(value, into = c('conditions', 'arrangements'), sep = ' ')
data
# A tibble: 1,000 × 2
conditions arrangements
<chr> <chr>
1 ???#?????? 4,4
2 ??..#??#??.???? 5,1
3 ?.?.???????##????? 1,2,8
4 .#????.????#?????? 2,1,1,2,1,1
5 ??????#????...#?... 9,1
6 .???.?????. 3,1,1
7 ??..?..???. 1,1
8 ??.??.#..?..??###?? 2,1,1,1,6
9 ????.???## 3,1,3
10 ???#?###?#?#.??? 1,1,7,1,1
# ℹ 990 more rows
Now that we have the puzzle input properly formatted, I wrote the following function to help facilitate identifying the number of possible arrangements based on the given criteria. The function reads in the conditions and arrangements, and then creates a grid of all possible combinations of working and broken hot springs. It then filters the grid based on the regex pattern of the given arrangements, and returns the number of rows in the filtered grid.
<- \(conditions, arrangements) {
determine_possible_arrangements <- conditions |> str_split('') |> unlist()
conditions
<- conditions |>
conditions set_names(paste0('c', 1:length(conditions)))
<- tibble(!!!conditions) |>
params pivot_longer(everything(), names_to = 'col_name')
<- params |>
params deframe() |>
as.list()
<- map(params, \(x) {
params if (x == '?') {
expr(c('.', '#'))
else {
} expr(as.character(!!x))
}
})
<- expr({
grid crossing(!!!params)
|> eval()
})
<- arrangements |>
arrangements str_split(',') |>
unlist()
<-
arrangements map(arrangements, \(x) paste0('#{', x, '}')) |> unlist()
<- glue::glue_collapse(arrangements, sep = '\\.+')
arrangements
<- glue::glue_collapse(c('^\\.*', arrangements, '\\.*$')) |> as.character()
arrangements
<- paste0('c', 1:length(grid)) |> syms()
cols
<- grid |>
grid mutate(c = paste(!!!cols, sep = ''))
<- grid |>
grid filter(str_detect(c, arrangements))
nrow(grid)
}
Now that we have our function written, let’s apply this for all rows in our puzzle input. We can use purrr::map2
to iterate over both the conditions and arrangements columns, and apply our function to each row. We can then sum the results to get our final answer.
<- map2(data$conditions, data$arrangements, \(conditions, arrangements) {
results
determine_possible_arrangements(conditions, arrangements)
.progress = TRUE)
},
|> unlist() |> sum() results
Reuse
Citation
@online{luu2023,
author = {Luu, Michael},
title = {Advent of {Code} 2023, {Day} 12},
date = {2023-12-23},
langid = {en}
}