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")][[1]]$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")
repeat{ # The dreaded repeat
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])][[1]]$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)