AoC2020 Days 5 to 7

2020-12-07

Days 5 and 6 were pretty uneventful, still relatively easy; the first one solvable trivially by transforming the input into a binary sequence and translating it into an integer, the second one needed to be carefully parsed but once done was solved just by applying `table` to it, so nothing unsurmontable. Day 7 however was a notch more complicated, in that it needed recursion, which is always an head-scratcher.

Technically it was reminiscent from day 14 of last year but simpler: the input consisted of sentences like "light red bags contain 1 bright white bag, 2 muted yellow bags." and "faded blue bags contain no other bags." and one needed to figure out how many bags a "shiny gold" bag contained, which necessited to go through the whole "reaction" path (i. e. `a=2b+4c; c=3d+4b; etc.`). For the parser I used the same method as for day 2 (i. e. `parse.one`) and then, lazily, use an operator that is normally a no-go in R: `repeat`. I am sure there would have been more elegant ways to do the job, but at least it worked and was fairly fast.

``````input <- readLines("input07.txt")
res <- lapply(input,parse_reac) #parse_reac is the parser I made, check out in the github repo to read it. It's fairly tedious though.
# res is the parsed input, each element contains:
# an element "a" that is the containing color,
# "b" a dataframe of what is contained in "a", where n is the number of bags and col their color.
# If the bag contains no other bags, b is NULL.
step <- res[sapply(res,function(x)x\$a=="shiny gold")][]\$b # I know it's ugly: go through all elements and return dataframe b if a is he color we need
step\$n <- as.integer(step\$n) # Why didn't I made the parser converts that to integer directly, i'll never know
step\$end <- FALSE # This vector is where we'll say if we reached the end of a path (i. e. "contains no bags")
replacement <- data.frame(n=NULL, col=NULL, end=NULL) # Empty dataframe in which we will put the result
for(i in 1:nrow(step)){
if(!step\$end[i]){ #If we didn't already reach the end of that particular path
sub <- res[sapply(res,function(x)x\$a==step\$col[i])][]\$b
if(!is.null(sub)){
sub\$n <- as.integer(sub\$n)*step\$n[i]
sub\$end <- FALSE
step\$end[i] <- TRUE
#One needs to keep the step that is done because we need to count those bags too.
replacement <- rbind(replacement, sub, step[i,])
}else{
step\$end[i]<-TRUE
replacement <- rbind(replacement, step[i,])
}
}else{
replacement <- rbind(replacement, step[i,])
}
}
step <- replacement
if(all(step\$end)){break} #If every path reached its end, we can stop
}
sum(step\$n)``````