Day 7

AdventOfCode > 2022

Part 1: What is the sum of the total sizes of those directories?

I manually downloaded my personal day 7 input file as a logged user, and here I get the data in a more appropriate shape.

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()
data <- 
    read_csv(
        here::here("2022/07_input"),
        col_names = c("line"),
        show_col_types = FALSE
    )

data %>% print(n = 30)
# A tibble: 1,087 × 1
   line               
   <chr>              
 1 $ cd /             
 2 $ ls               
 3 dir bfbjzfd        
 4 dir mbc            
 5 dir psqmv          
 6 dir qqpgw          
 7 59022 rrqzqwl.frp  
 8 dir sscj           
 9 dir vpfdwq         
10 dir zzp            
11 $ cd bfbjzfd       
12 $ ls               
13 125000 bmzjjgzc.dcr
14 dir brmgzjp        
15 165351 hgm         
16 dir rhrqttg        
17 dir zfdc           
18 $ cd brmgzjp       
19 $ ls               
20 298676 zzp.wrm     
21 $ cd ..            
22 $ cd rhrqttg       
23 $ ls               
24 dir hmz            
25 dir hpcrbfq        
26 $ cd hmz           
27 $ ls               
28 297949 lqcg        
29 $ cd ..            
30 $ cd hpcrbfq       
# … with 1,057 more rows

I build a helper function to locate the path of each line using purrr::accumulate. @drob, thanks for your tip

cd <- function(path, dir = NA) {
    if (any(is.na(dir))) return(path)
    if (any(dir == "..")) return(head(path, -1))
    return(c(path, paste0(tail(path, 1), "/", dir)))
}

cd("c", cd("users", cd("jordi", cd("docs"))))
[1] "c"                  "c/users"            "c/users/jordi"     
[4] "c/users/jordi/docs"
paths <- data %>% 
    mutate(path = line %>% 
          str_extract("cd (.*)") %>% 
          str_remove("cd ")
    ) %>% 
    mutate(path = accumulate(path, cd)) %>% 
    unnest(path)

paths %>% 
    print(n = 40)
# A tibble: 6,246 × 2
   line                path             
   <chr>               <chr>            
 1 $ cd /              /                
 2 $ ls                /                
 3 dir bfbjzfd         /                
 4 dir mbc             /                
 5 dir psqmv           /                
 6 dir qqpgw           /                
 7 59022 rrqzqwl.frp   /                
 8 dir sscj            /                
 9 dir vpfdwq          /                
10 dir zzp             /                
11 $ cd bfbjzfd        /                
12 $ cd bfbjzfd        //bfbjzfd        
13 $ ls                /                
14 $ ls                //bfbjzfd        
15 125000 bmzjjgzc.dcr /                
16 125000 bmzjjgzc.dcr //bfbjzfd        
17 dir brmgzjp         /                
18 dir brmgzjp         //bfbjzfd        
19 165351 hgm          /                
20 165351 hgm          //bfbjzfd        
21 dir rhrqttg         /                
22 dir rhrqttg         //bfbjzfd        
23 dir zfdc            /                
24 dir zfdc            //bfbjzfd        
25 $ cd brmgzjp        /                
26 $ cd brmgzjp        //bfbjzfd        
27 $ cd brmgzjp        //bfbjzfd/brmgzjp
28 $ ls                /                
29 $ ls                //bfbjzfd        
30 $ ls                //bfbjzfd/brmgzjp
31 298676 zzp.wrm      /                
32 298676 zzp.wrm      //bfbjzfd        
33 298676 zzp.wrm      //bfbjzfd/brmgzjp
34 $ cd ..             /                
35 $ cd ..             //bfbjzfd        
36 $ cd rhrqttg        /                
37 $ cd rhrqttg        //bfbjzfd        
38 $ cd rhrqttg        //bfbjzfd/rhrqttg
39 $ ls                /                
40 $ ls                //bfbjzfd        
# … with 6,206 more rows

I group and summarize the sizes and thenfilter to get the sum of sizes:

sizes <- paths %>% 
    filter(str_detect(line, "^[0-9]")) %>% 
    group_by(path) %>% 
    summarize(size = line %>%
        str_extract("^[0-9]+") %>%
        as.numeric() %>%
        sum()
    ) %>% 
    arrange(-size)

sizes
# A tibble: 199 × 2
   path                              size
   <chr>                            <dbl>
 1 /                             47052440
 2 //psqmv                       23595140
 3 //psqmv/tbcz                  21231784
 4 //vpfdwq                      17348139
 5 //psqmv/tbcz/lwmjgnh          15124476
 6 //vpfdwq/zzp                  11958790
 7 //vpfdwq/zzp/zbdpt            10519770
 8 //psqmv/tbcz/lwmjgnh/pnhcpprn  7278116
 9 //vpfdwq/zzp/zbdpt/jjmfpmnn    7268994
10 //psqmv/tbcz/lwmjgnh/zbprw     5616207
# … with 189 more rows
sizes %>% 
    filter(size < 100000) %>% 
    pull(size) %>% 
    sum()
[1] 1232307

Part 2: Find the smallest directory that, if deleted, would free up enough space on the filesystem to run the update. What is the total size of that directory?

Solution for part 2:

total <- 70000000
required <- 30000000
used <- head(sizes, 1) %>% pull(size)

sizes %>% 
  filter(size >= (required - (total - used))) %>% 
  arrange(size) %>% 
  head(1)
# A tibble: 1 × 2
  path                           size
  <chr>                         <dbl>
1 //vpfdwq/zzp/zbdpt/jjmfpmnn 7268994

Solution

library(tidyverse)

data <- 
    read_csv(
        here::here("2022/07_input"),
        col_names = c("line"),
        show_col_types = FALSE
    )

cd <- function(path, dir = NA) {
    if (any(is.na(dir))) return(path)
    if (any(dir == "..")) return(head(path, -1))
    return(c(path, paste0(tail(path, 1), "/", dir)))
}

sizes <- data %>% 
    mutate(path = line %>% 
          str_extract("cd (.*)") %>% 
          str_remove("cd ")
    ) %>% 
    mutate(path = accumulate(path, cd)) %>% 
    unnest(path) %>% 
    filter(str_detect(line, "^[0-9]")) %>% 
    group_by(path) %>% 
    summarize(size = line %>%
        str_extract("^[0-9]+") %>%
        as.numeric() %>%
        sum()
    ) %>% 
    arrange(-size)

sizes

sizes %>% 
    filter(size < 100000) %>% 
    pull(size) %>% 
    sum()

total <- 70000000
required <- 30000000
used <- head(sizes, 1) %>% pull(size)

sizes %>% 
  filter(size >= (required - (total - used))) %>% 
  arrange(size) %>% 
  head(1)