Day 4

AdventOfCode > 2022

Part 1: In how many assignment pairs does one range fully contain the other?

I manually downloaded my personal day 4 input file as a logged user, and here I get the data.

library(tidyverse)
── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
✔ ggplot2 3.4.0          ✔ purrr   0.3.5     
✔ tibble  3.1.8          ✔ dplyr   1.0.10    
✔ tidyr   1.2.1          ✔ stringr 1.4.1.9000
✔ readr   2.1.3          ✔ forcats 0.5.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
# remotes::install_github("tidyverse/stringr", force = TRUE)
packageVersion("stringr") # 1.4.1.9000
[1] '1.4.1.9000'
data <- 
    read_csv(
        here::here("2022/04_input"),
        col_names = c("first", "second"),
        show_col_types = FALSE
    )
data %>% print(n = 30)
# A tibble: 1,000 × 2
   first second
   <chr> <chr> 
 1 1-93  2-11  
 2 26-94 26-94 
 3 72-92 48-88 
 4 36-37 37-52 
 5 2-98  1-98  
 6 1-83  1-84  
 7 74-79 76-76 
 8 66-85 66-86 
 9 6-73  6-73  
10 31-57 30-58 
11 1-98  1-98  
12 28-47 55-97 
13 29-71 70-72 
14 40-53 40-53 
15 14-71 39-71 
16 19-98 18-94 
17 94-96 81-95 
18 79-98 79-97 
19 52-66 60-61 
20 2-3   8-89  
21 53-59 59-83 
22 79-81 3-80  
23 14-84 84-92 
24 90-90 7-89  
25 10-76 11-76 
26 9-31  10-12 
27 8-8   8-72  
28 2-97  1-96  
29 3-33  2-94  
30 3-5   4-99  
# … with 970 more rows

I separate both columns:

data %>%
    separate(first, c("first_start", "first_end"), sep = "-") %>% 
    separate(second, c("second_start", "second_end"), sep = "-") 
# A tibble: 1,000 × 4
   first_start first_end second_start second_end
   <chr>       <chr>     <chr>        <chr>     
 1 1           93        2            11        
 2 26          94        26           94        
 3 72          92        48           88        
 4 36          37        37           52        
 5 2           98        1            98        
 6 1           83        1            84        
 7 74          79        76           76        
 8 66          85        66           86        
 9 6           73        6            73        
10 31          57        30           58        
# … with 990 more rows

separate(first, c(“first_start”, “first_end”), sep = “-”) %>%

separate(second, c(“second_start”, “second_end”), sep = “-”)

I check if the first or second range in each row are fully contained one in another:

data %>% 
    separate(first, c("first_start", "first_end"), sep = "-") %>% 
    separate(second, c("second_start", "second_end"), sep = "-") %>% 
    mutate(across(everything(), as.numeric)) %>% 
    rowwise() %>% 
    mutate(fully_contain = 
        (first_start >= second_start & first_end <= second_end) | 
        (second_start >= first_start & second_end <= first_end)
    )
# A tibble: 1,000 × 5
# Rowwise: 
   first_start first_end second_start second_end fully_contain
         <dbl>     <dbl>        <dbl>      <dbl> <lgl>        
 1           1        93            2         11 TRUE         
 2          26        94           26         94 TRUE         
 3          72        92           48         88 FALSE        
 4          36        37           37         52 FALSE        
 5           2        98            1         98 TRUE         
 6           1        83            1         84 TRUE         
 7          74        79           76         76 TRUE         
 8          66        85           66         86 TRUE         
 9           6        73            6         73 TRUE         
10          31        57           30         58 TRUE         
# … with 990 more rows

Here the full code with the result:

library(tidyverse)

fully_contain <- function(df) {
    df %>% 
        mutate(across(everything(), as.numeric)) %>% 
        rowwise() %>% 
        mutate(fully_contain = 
            (first_start >= second_start & first_end <= second_end) | 
            (second_start >= first_start & second_end <= first_end)
        ) %>%
        ungroup()
}

read_csv(
        here::here("2022/04_input"),
        col_names = c("first", "second"),
        show_col_types = FALSE
    ) %>%
    separate(first, c("first_start", "first_end"), sep = "-") %>% 
    separate(second, c("second_start", "second_end"), sep = "-") %>% 
    fully_contain() %>% 
    summarise(fully_contain = sum(fully_contain))
# A tibble: 1 × 1
  fully_contain
          <int>
1           503

Part 2: In how many assignment pairs do the ranges overlap?

overlap <- function(df) {
   df %>% 
        mutate(across(everything(), as.numeric)) %>% 
        rowwise() %>% 
        mutate(overlap = 
            list(intersect(first_start:first_end, second_start:second_end))
        ) %>% 
        mutate(overlap = length(overlap) > 0) %>% 
        ungroup()
}
read_csv(
        here::here("2022/04_input"),
        col_names = c("first", "second"),
        show_col_types = FALSE
    ) %>%
    separate(first, c("first_start", "first_end"), sep = "-") %>% 
    separate(second, c("second_start", "second_end"), sep = "-") %>% 
    overlap() %>% 
    summarise(overlap = sum(overlap))
# A tibble: 1 × 1
  overlap
    <int>
1     827