# techniques: split-apply-combine
#' Day 02: Inventory Management System
#'
#' [Inventory Management System](https://adventofcode.com/2018/day/2)
#'
#' @name day02
#' @rdname day02
#' @details
#'
#' **Part One**
#'
#' You stop falling through time, catch your breath, and check the screen
#' on the device. "Destination reached. Current Year: 1518. Current
#' Location: North Pole Utility Closet 83N10." You made it! Now, to find
#' those anomalies.
#'
#' Outside the utility closet, you hear footsteps and a voice. "...I'm not
#' sure either. But now that [so many people have
#' chimneys]{title="This is, in fact, roughly when chimneys became common in houses."},
#' maybe he could sneak in that way?" Another voice responds, "Actually,
#' we've been working on a new kind of *suit* that would let him fit
#' through tight spaces like that. But, I heard that a few days ago, they
#' lost the prototype fabric, the design plans, everything! Nobody on the
#' team can even seem to remember important details of the project!"
#'
#' "Wouldn't they have had enough fabric to fill several boxes in the
#' warehouse? They'd be stored together, so the box IDs should be similar.
#' Too bad it would take forever to search the warehouse for *two similar
#' box IDs*..." They walk too far away to hear any more.
#'
#' Late at night, you sneak to the warehouse - who knows what kinds of
#' paradoxes you could cause if you were discovered - and use your fancy
#' wrist device to quickly scan every box and produce a list of the likely
#' candidates (your puzzle input).
#'
#' To make sure you didn't miss any, you scan the likely candidate boxes
#' again, counting the number that have an ID containing *exactly two of
#' any letter* and then separately counting those with *exactly three of
#' any letter*. You can multiply those two counts together to get a
#' rudimentary [checksum](https://en.wikipedia.org/wiki/Checksum) and
#' compare it to what your device predicts.
#'
#' For example, if you see the following box IDs:
#'
#' - `abcdef` contains no letters that appear exactly two or three times.
#' - `bababc` contains two `a` and three `b`, so it counts for both.
#' - `abbcde` contains two `b`, but no letter appears exactly three
#' times.
#' - `abcccd` contains three `c`, but no letter appears exactly two
#' times.
#' - `aabcdd` contains two `a` and two `d`, but it only counts once.
#' - `abcdee` contains two `e`.
#' - `ababab` contains three `a` and three `b`, but it only counts once.
#'
#' Of these box IDs, four of them contain a letter which appears exactly
#' twice, and three of them contain a letter which appears exactly three
#' times. Multiplying these together produces a checksum of `4 * 3 = 12`.
#'
#' *What is the checksum* for your list of box IDs?
#'
#' **Part Two**
#'
#' Confident that your list of box IDs is complete, you're ready to find
#' the boxes full of prototype fabric.
#'
#' The boxes will have IDs which differ by exactly one character at the
#' same position in both strings. For example, given the following box IDs:
#'
#' abcde
#' fghij
#' klmno
#' pqrst
#' fguij
#' axcye
#' wvxyz
#'
#' The IDs `abcde` and `axcye` are close, but they differ by two characters
#' (the second and fourth). However, the IDs `fghij` and `fguij` differ by
#' exactly one character, the third (`h` and `u`). Those must be the
#' correct boxes.
#'
#' *What letters are common between the two correct box IDs?* (In the
#' example above, this is found by removing the differing character from
#' either ID, producing `fgij`.)
#'
#' @param x a character vector of box IDs to checksum
#' @return For Part One, `checksum_box_id(x)` returns the number of IDs with
#' exactly 2 characters times number with exactly 3 characters. For Part Two,
#' `find_one_character_neighbors(x)` the characters shared by the two items
#' that share all but one character.
#' @export
#' @examples
#' x <- c("abcdef", "bababc", "abbcde", "abcccd",
#' "aabcdd", "abcdee", "ababab")
#' checksum_box_id(x)
#' x <- c("abcde", "fghij", "klmno", "pqrst",
#' "fguij", "axcye", "wvxyz")
#' find_one_character_neighbors(x)
checksum_box_id <- function(x) {
char_counts <- x %>%
purrr::map(str_tokenize) %>%
purrr::map(table)
have_exactly_three <- char_counts %>%
purrr::keep(~ 3 %in% .x) %>%
length()
have_exactly_two <- char_counts %>%
purrr::keep(~ 2 %in% .x) %>%
length()
have_exactly_three * have_exactly_two
}
#' @rdname day02
#' @export
find_one_character_neighbors <- function(x) {
# Try dropping each character position. Look for duplicates on resulting
# items.
seq_len(nchar(x[1])) %>%
purrr::map(~ check_for_one_character_neighbors(x, .x)) %>%
purrr::flatten_chr()
}
check_for_one_character_neighbors <- function(x, position) {
x %>%
purrr::map(str_tokenize) %>%
purrr::map(drop_element, position) %>%
purrr::map_chr(paste0, collapse = "") %>%
pull_duplicates()
}
drop_element <- function(xs, i) {
xs[-i]
}
pull_duplicates <- function(xs) {
xs[duplicated(xs)]
}
str_tokenize <- function(x) {
unlist(strsplit(x, ""))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.