Day 9

Advent of Code: Worked Solutions

About
Date

December 9, 2024

Setup

# Libraries
library(tidyverse)

# Read input from file
input <- read_lines("../input/day09.txt", skip_empty_rows = TRUE) |> 
  str_split_1("") |> 
  as.integer()

Part 1

Define custom file functions:

move_files <- function(filesys) {
  repeat {
    first_blank <- min(which(is.na(filesys)))
    last_file   <- max(which(!is.na(filesys)))
    
    # If all files have been compressed, exit
    if (first_blank > last_file) break
    
    # Otherwise, move the last file into the first blank location
    filesys[first_blank] <- filesys[last_file]
    filesys[last_file]   <- NA_integer_
  }
  filesys
}

checksum <- function(filesys) {
  filesys |> 
    imap_int(\(x, idx) if_else(is.na(x), 0, x * (idx - 1))) |> 
    sum() |> 
    format(scientific = FALSE)
}

Run puzzle input:

# Uncompress file layout
filesys <- input|> 
  imap(function(x, idx) {
    # Even entries are files; odd entries are spaces
    file_id <- if_else(idx %% 2 == 1, floor(idx / 2), NA_integer_)
    rep(file_id, x)
  }) |> 
  unlist()

filesys |> 
  move_files() |> 
  checksum()
[1] "6330095022244"

Part 2

Update the compression function:

move_blocks <- function(filesys) {
  for (file_id in max(na.omit(filesys)):1) {
    
    # Pull the location and length of the file block for the current ID
    file_block <- which(filesys == file_id)
    n <- length(file_block)
    
    # Pull indices of all empty values before the current file block
    empty_idx <- which(is.na(filesys[1:min(file_block)]))
    
    # Pull all valid starting indices of empty blocks of the right length
    if (n == 1) {
      valid_idx <- empty_idx
    } else {
      valid_block <- replace_na(lead(empty_idx, n - 1) - empty_idx == n - 1, FALSE)
      valid_idx <- empty_idx[valid_block]
    }
    
    # If valid indices exist, move the file block to the first valid location
    if (length(valid_idx) > 0) {
      idx_start <- min(valid_idx)
      filesys[idx_start:(idx_start + n - 1)] <- file_id
      filesys[file_block] <- NA_integer_
    }
    
  }
  filesys
}

Run puzzle input:

filesys |> 
  move_blocks() |> 
  checksum()
[1] "6359491814941"