day05.R (2511B)
1 #!/usr/bin/env Rscript 2 3 source("src/utils.R") 4 5 test_input <- c( 6 "3-5", 7 "10-14", 8 "16-20", 9 "12-18", 10 "", 11 "1", 12 "5", 13 "8", 14 "11", 15 "17", 16 "32" 17 ) 18 puzzle_input <- aoc_input(5) 19 20 parse_input <- function(input_lines) { 21 blank_idx <- which(input_lines == "") 22 parsed_input <- list() 23 24 parsed_input$fresh_ranges <- input_lines[1:(blank_idx - 1)] |> 25 strsplit("-") |> 26 unlist() |> 27 as.numeric() |> 28 matrix(nrow = blank_idx - 1, byrow = TRUE) 29 parsed_input$fresh_ranges <- parsed_input$fresh_ranges[order( 30 parsed_input$fresh_ranges[, 1], parsed_input$fresh_ranges[, 2] 31 ), ] 32 33 parsed_input$ingredient_ids <- input_lines[(blank_idx + 1):length(input_lines)] |> 34 as.numeric() |> 35 sort() 36 37 parsed_input 38 } 39 40 test_ingredients <- function(ingredient_ids, fresh_ranges) { 41 is_fresh <- rep(NA, length(ingredient_ids)) 42 43 fresh_idx <- 1 44 for (ingredient_idx in seq_along(ingredient_ids)) { 45 while ( 46 fresh_idx <= nrow(fresh_ranges) && 47 fresh_ranges[fresh_idx, 2] < ingredient_ids[ingredient_idx] 48 ) { 49 fresh_idx <- fresh_idx + 1 50 } 51 if (fresh_idx > nrow(fresh_ranges)) { 52 is_fresh[ingredient_idx:length(ingredient_ids)] <- FALSE 53 break 54 } 55 is_fresh[ingredient_idx] <- ingredient_ids[ingredient_idx] >= fresh_ranges[fresh_idx, 1] 56 } 57 is_fresh 58 } 59 60 part1 <- function(input_lines) { 61 input_parsed <- parse_input(input_lines) 62 sum(test_ingredients(input_parsed$ingredient_ids, input_parsed$fresh_ranges)) 63 } 64 65 test_part1 <- function() { 66 stopifnot(part1(test_input) == 3) 67 } 68 69 count_fresh_ids <- function(fresh_ranges) { 70 add_remaining_fresh_ids <- function(row_id, last_fresh_id) { 71 new_ids <- if (fresh_ranges[row_id, 2] <= last_fresh_id) { 72 0 73 } else if (fresh_ranges[row_id, 1] <= last_fresh_id) { 74 fresh_ranges[row_id, 2] - last_fresh_id 75 } else { 76 fresh_ranges[row_id, 2] - fresh_ranges[row_id, 1] + 1 77 } 78 79 if (row_id == nrow(fresh_ranges)) { 80 new_ids 81 } else { 82 new_ids + 83 add_remaining_fresh_ids( 84 row_id + 1, 85 max(last_fresh_id, fresh_ranges[row_id, 2]) 86 ) 87 } 88 } 89 add_remaining_fresh_ids(1, 0) 90 } 91 92 part2 <- function(input_lines) { 93 input_parsed <- parse_input(input_lines) 94 count_fresh_ids(input_parsed$fresh_ranges) 95 } 96 97 test_part2 <- function() { 98 part2(test_input) == 14 99 } 100 101 main <- function() { 102 test_part1() 103 cat("Part 1 solution: ", part1(puzzle_input), "\n") 104 test_part2() 105 cat(sprintf("Part 2 solution: %0.0f\n", part2(puzzle_input))) 106 } 107 108 main()