In the process, I ran into a real puzzler -- a bug that I and several friends looked at and couldn't quickly solve. It turned out to be really basic Ruby.
I had developed the following code as part of the answer to CtCI's problem 9.4: Create all the subsets from a set (you can find the complete solution here).
def ss_raw set @result_raw << set return if set.size == 1 set.each_index do |i| tmp = set tmp.delete_at i ss_raw(tmp) end endThe intent of this code was to recursively remove one element from the input and generate the subsets. The tmp variable was intended as a proxy for the set variable so that the each_index block could process each subset by deleting one element at a time. It didn't work and gave some really perplexing results, apparently replacing the contents of @result_raw rather than appending to it.
Unfortunately, I forgot the basics:
tmp = setdoesn't create a new variable, it simply creates a new pointer to the same location in storage that set points to. Therefore, modifying tmp also modifies set and the whole process goes south. The solution? Just say
tmp = set.cloneand you get a new and separate variable and the method works as expected.
In many cases, an oversight like this won't cause a problem, but in this cae it wound up modifying the method parameter as well as modifying the basis of the each_index block... a definite no-no and exactly what I was trying to avoid in the first place.
Hopefully this little reminder will help someone else avoid the pain.