I write less deeply-nested code now that I program in R. When writing code poorly in other programs, I’d often use nested IF statements (hi, Excel!). Debugging that often looked like counting my nesting depth out loud: add one for every (, subtract one for every ).
That strategy formed the basis for my solution today. And I was excited to do Part 2 with arithmetic, not writing new code.
Part 1
Strategy: maintain counter of open braces, decreasing for closed braces.
So `{{<a>},{<a>},{<a>},{<a>}}` = 1 2 2 2 2. Sum = 9.
library(pacman)
p_load(stringr, testthat)
# cancel the character after !
cancel_chars <- function(x){ gsub("!.", "", x) }
group_score <- function(dat){
clean <- gsub("<.*?>", "" , dat) # non-greedy regex to remove garbage
lvl <- 1 # depth of braces nesting
counts <- rep(0, nchar(clean)) # default value for non-{ characters
for(i in seq.int(nchar(counts))){
if(str_sub(clean, i, i) == "{"){ # log the nested depth and increment counter
counts[i] <- counts[i] + lvl
lvl <- lvl + 1
}
if(str_sub(clean, i, i) == "}"){
lvl <- lvl - 1
}
}
sum(counts)
}
# Test
expect_equal(group_score("{{{}}}"), 6)
expect_equal(group_score("{{},{}}"), 5)
expect_equal(group_score("{{{},{},{{}}}}"), 16)
dat <- scan("09_1_dat.txt", "character")
group_score(cancel_chars(dat)) # 15922
Part 2
The answer is the total number of characters, minus:
- The characters canceled by
! - The bracketing `<>` for each garbage string
- The valid characters remaining after removing the garbage in Part 1
To wit:
cleaned <- cancel_chars(dat)
nchar(cleaned) -
2*str_count(string = cleaned, pattern = fixed(">")) -
nchar(gsub("<.*?>", "" , cleaned))
# 7314