The Brainfuck Quest

One of my study resources for learning new languages is SPOJ. Actually, I’ve used it only to learn Ruby so far, but I’ll use it for any one to come (Python?, LISP?).

Although SPOJ international has a much bigger user base and challenge level, I’m giving more attention to SPOJ Brazil, and BRAIN, one of its problems, is giving me much more headache then it should do.

I decided to give it another try, but the code was big enough for me to try to fix it. But this time I will make it different by adding unit tests.

The old testing process

The testing process consisted of running the tests given in the problem site. But my code pass them and still fails in the tests given when the code is submitted.

The new testing process

I put some unit tests (thanks for embedding unit tests, Matz) to test individual commands of my interpreter, and I found the first problem with it. The # command was printing the first ten bytes of the input, instead of the first ten bytes of the vector. The tests given in the problem site didn’t cover this case.

Then I added tests for the four basic math operations. The divide test is quite good, since the loop nesting stack is something that goes seven levels up in the stack!

My code just blowed up when I tried to run it. After some search, I found nothing. After a lot of more searching, I found a little bug: When the interpreter read the ] command, it wasn’t appending the following code in the right order. The other tests didn’t find this error because the loops were quite simple, with just one nested loop.

Then again I tried to upload it, but it failed once more. Now, I let it there for a couple of days, and then, I found another problems with the whole nesting system. Now I have to say that what saved my life was a piece of paper and a pen. I drawn the whole nesting process, making arrows for variables names and arrays, and it all became clear to me. After a little brainstorming (and more drawing), I re-wrote it all and all my tests passed!

I was already screaming bad words when I realized it had to pass SPOJs tests too, and then it all came to ruins when I got a TLE in my face. The problem has a 1 second time limit. The problem became performance.

Profiling

I really, really thought about re-writing everything in C and upload it just to prove my algorithm works. I decided to give Ruby’s profiler a try, by running the code with the -r profile option.

The results

At the beginning I thought the Range#each method was the cause of my problems, but it isn’t because all relevant code runs inside one of them. I thought about whining about the language too, but for sure, the problem is with my algorithm.

Now I have a apparently functional brainfuck interpreter who does not run fast enough for SPOJs tests. The source is here. I don’t want to give up on it. My plans were to post it when it passes, but I just can’t see any solution in the near future, and I don’t want to abandon the blog either.

I’ll make more posts anytime this issue evolves. Or not.

Testing = insurance?

Some people think (and they\’re right) that professional developers write tests. So, if you don’t do them, you’re an amateur. In my current job, I don’t write tests. And I’m not very happy about it, because the decision-making process of whether testing or not is beyond my control.

Something that I must say: In my pet-projects is the complete opposite. Since I’m quite new to testing, I must say it is a very addictive thing. This week for example I almost introduced a bug in the code, and was saved by my humble integration tests.

What do you think about people who do not insurance their cars? Irresponsible? I got two cars stolen on the last four years, and I must say it: You must insurance your car before taking it out of the garage. You just stop complaining about a R$150,00 monthly fee after you get a R$33.000,00 check from them and buy a new one.

[crazy_angel_investor_bait]But there\’s no company that insurances our software[/crazy_angel_investor_bait]. Meanwhile, we can “insurance” our own code by writing tests. And also set goals for it, like stop coding because all tests passed. This is useful for people who seems to spend a lot of time on trivial matters. Hey, you software do what it is supposed to do. Go on with your life.

So here is the (poor) analogy: You can’t tell when you’re gonna have a bug in your code, just like you don’t know when you’re gonna have your car stolen. You won’t have a insurance company to help your minimize your losses, but with tests, you know that your code would break some other working feature, and the number of bugs that do go public drops down heavily.

From today on, every time you go to a place where people don’t write tests, or hear someone say they don’t do it for whatever the reason, think about them as people who take the risk of losing a some tens of thousands of dollars (or brazilian reais in my case) everytime they drive their cars.