Advent of Code 2020 Day 2

Author

Nathan Moore

— Day 2: Password Philosophy —

The North Pole Toboggan Rental Shop needs help with validating some passwords.

How many passwords are valid according to their policies?

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.6
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.1     ✔ tibble    3.3.0
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.2.0     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
inputfile = here::here("2020", "data-2020-02.txt")

# data for a df 
toboggan <- read_csv(inputfile, col_names = FALSE)
Rows: 1000 Columns: 1
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (1): X1

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

First attempt with str_split and unnest_wider

# first attempt with str_split and unnest_wider
# no_good <- toboggan %>% 
#   mutate(split1 = str_split(X1, " ")) %>% 
#   unnest_wider(split1) %>% 
#   rename(lim = `...1`, letter = `...2`, password = `...3`) %>% 
#   mutate(split2 = str_split(lim, "-")) %>% 
#   unnest_wider(split2) %>% 
#   rename(lim1 = `...1`, lim2 = `...2`) %>% 
#   mutate(
#     letter = str_remove(letter, ":"), 
#     lim1 = as.numeric(lim1), 
#     lim2 = as.numeric(lim2)
#     ) %>% 
#   select(-X1, -lim)

separate() is way better!

tob_split <- toboggan %>% 
  separate(X1, sep = " ", c("lims", "lett", "pw")) %>% 
  separate(lims, sep = "-", c("lo", "hi")) %>% 
  mutate(
    lett = str_remove(lett, ":"), 
    lo = as.integer(lo), 
    hi = as.integer(hi)
  )

# find rows which satisfy conditions
check_func <- function(lo, hi, lett, pw) {
  cnt = str_count(pw, lett)
  # print(c(l1, l2, cnt, l1 <= cnt, cnt <= l2))
  (lo <= cnt && cnt <= hi)
}

# pmap() for multiple arguments
check_1 <- tob_split %>% 
  mutate(pass = pmap_lgl(tob_split, check_func))

# part one answer
sum(check_1$pass)
[1] 500

— Part Two —

The password rules are actually different!

How many passwords are valid according to the new interpretation of the policies?

# check 2 function
check_pos = function(lo, hi, lett, pw) {
  pos = str_locate_all(pw,lett)
  pos_vect = pos[[1]][,1]
  check1 = lo %in% pos_vect
  check2 = hi %in% pos_vect
  xor(check1, check2)
}

# run the second function
check_2 <- tob_split %>% 
  mutate(pos = pmap_lgl(tob_split, check_pos))

# part two answer
sum(check_2$pos)
[1] 313