Advent of Code 2023 - Day 1Trebuchet?!

R | Problem statement | Source code | Tags: String manipulation

Part 1

At the beginning, the language choice of R really created more problems than it solved. I know I'm supposed to use vectorized operations etc. etc., but figuring out the data types for each step was a nightmare. Everything might be a list or a vector; I don't know how to index them and I don't know when to use sapply or lapply.

For the first part, to extract number digits, I just remove all non-digits from the string. Then, I can take the first and last digit of each number, concatenate them, and sum them up. It turns out that getting one character from a string is quite intractable in R because you need substr, but vectorized functions made it at least intuitive to read.

solve1 <- function(data) {
nums <- gsub("[^0-9]", "", data)
nums <- paste0(substr(nums, 1, 1), substr(nums, nchar(nums), nchar(nums)))
cat(sum(as.numeric(nums)), "\n")
}
R

Part 2

At first, I had a string-to-number mapping, and I just replace each string with its corresponding number, but there's a major pitfall: replacements need to be done left-to-right, not in the order of digit magnitude. For example, the example input:

twone

The approach of first replacing "one" and then "two" would turn this into "tw1", which is incorrect; instead it should be "2ne". Therefore I need to do a single gsub, passing in a disjunction of all strings to be replaced. Then for each match, I can look up the corresponding digit and replace it. However it turns out that R does not have a built-in equivalent of JavaScript's String.replaceAll that can take a function as the replacement argument. I found the gsubfn package to do this for me.

pattern <- paste(names(substitutions), collapse = "|")
data <- gsubfn(pattern, function(w) substitutions[[w]], data)
nums <- gsub("[^0-9]", "", data)
nums <- paste0(substr(nums, 1, 1), substr(nums, nchar(nums), nchar(nums)))
cat(sum(as.numeric(nums)), "\n")
R