|R Advent: Days 6-10
||[Feb. 26th, 2016|08:25 am]
Days 6-10 start to expose some interesting language features. |
Day 6 [LOC: 15/11]
R lets you subset arrays using a vector of indices. This very handy, and it interacts with the ":" (sequence) operator in a really intuitive way. Which is all great if you want to do things to subsets that form big contiguous blocks (as is the case in this puzzle). If you want to operate on random values scattered throughout the array, it gives you plaid, which is probably not what you want; instead, you have to use cbind() to combine your vectors of N indices for each of M dimensions into an MxN array and use that. I always have a hard time remembering cbind(); Maybe explaining it here will help.
This is the first one I had to do a substantial amount of cleanup to the input; that's what all the gsub commands at the beginning are for. I feel like that doesn't really belong in this code, and that the proper solution is for whatever system is generating the inputs to do it in a form that better matches the end use.
Day 7 [LOC: 27/1]
Oh, man, this craziness. R has a function named "do.call" that lets you dynamically construct a function call from the name of the function and a list of arguments. Most of the time, you don't wanna do that. Most of the time, computing on the language like this just gives you a very elaborate and indirect way of shooting yourself in the foot with a bazooka. But when it is actually what you want to do, it's beautiful. I mean, this puzzle is literally a bunch of instructions to be evaluated. So just, y'know. Do exactly that. Boom.
Day 8 [LOC: 21/4]
Ugh, string encoding. I feel like if you ever had to deal with a gross mishmash of string escaping and encoding like this in the real world, the right answer would be to move upstream until you could make the problem go away. I'm not sure whether there's a more elegant solution using mind-twisting regexps or if that's the trap to avoid, but I found it easiest just to completely ignore what the data is supposed to mean and split it into a sequence of individual characters to scan for for the patterns of interest.
Day 9 [LOC: 10/1]
There are packages for doing the Traveling Salesman Problem, but if you need the optimal solution, the only way to know you have the right answer is to exhaustively test all possible routes. Which grows factorially, but fortunately there are only 8 stops, so it's still tractable. I feel like there's probably a more concise way of turning the input into a distance matrix, but I guess six lines of code isn't bad.
Day 10 [LOC: 9/4]
Always check to see if the function you need already exists. Run-length encoding is commonly-enough used in statistics that there's a function in the R core ("rle") that does it. If it weren't for the loop, I bet you could get this down to a one-liner, though whether it would be intelligible is another matter...