Sunday, January 18, 2009

Code Golfing in Ruby - part 1

About two years ago, while looking for some material about Ruby programming, I came across some website related to golf. If this is the first time you hear about golfing as a subject related to programming, which we can shortly define as "trying to solve a coding problem using the least number of keystrokes". I only know two golf related websites still in activity:
  • - anarchy golf, which is quite active, where one can challenge the problems with any of the 66 supported languages,
  • - Codegolf, which supports only 4 languages (Perl, PHP, Python and Ruby). Even if my golfing experience is quite short, I still would like to introduce some tips for beginners to get started in golfing. Some people might say that code golfing is a bad practice, but I think there are some useful things to learn from it.

When you start solving a problem, you will firstly implement an obvious algorithm, and then try to shorten your code the most you can. Then you might start to look for alternative syntax with the same meaning, for useless processing, and maybe think about another way to solve the problem, etc.

During all this process, you will first learn a lot about the syntax of the language you are using to solve you problem. Do not misinterpret my words: I really do not recommend you to practice golfing in order to learn a new language! In this case, I would better recommend to solve problems from the Project Euler. What I am trying to say is that to solve a golfing problem, you will certainly have to explore the language syntax, and implement multiple algorithms, which is a profitable experience.

Now let's get to the point of this post, which is to introduce these ruby golfing tips.

In this first post, we will focus on making use of predefined variables.
You will find in this ruby language quick reference page that there are a few predefined variables with a short name starting by the dollar sign. Let's have a look at the following ones:
$/  # The input record separator, newline by default.
$* # Command line arguments given for the script sans args.
$$ # The process number of the Ruby running this script.

As written in this documentation, $$ is a non-assignable variable containing a number which is usually bigger than 1000. Let's say that you need to iterate over a certain large number of times, and you need the number of the current iteration. In this case, you can use this already initialized variable as follows:
$$.times{|i|}

# here's the value I have on my current irb session:
rb(main):001:0> p$$
16434
=> nil

#You can also make a big range like this:
(0..$$)

Then suppose than you need to write a newline character into you script, using the predefined variable $/ will be one byte shorter than "\n".
irb(main):001:0> p$/
"\n"
=> nil

The predefined non-assignable variable $*, which contains the command line argument can be used when you need an empty array and can limit the number of calls to it. The advantage of this variable is that it contains an already initialized array. In a normal case, you would need to initialize an array like this: a=[]. Even if the variable name "$*" is 2 bytes long, it can be useful if you find a way to use it without having to name it too often. Look by yourself in irb:
irb(main):001:0> p$*
[]
=> nil

It was a little short for this first part, but I hope some people will find it useful. You can look for other predefined variables, and imagine the ways you can use them properly to shorten your code length, and I am pretty sure there is still a lot to do in this field.

See you soon for the second part of this article!

1 comment:

  1. Hi Guillaume, I saw the link from Facebook. Good to see you've kept up with your coding.

    I think the use of variables like '$$' is the kind of thing that turns me away from Ruby. I've been doing a little Ruby on Rails recently and found the code less readable than the Python I'm used to. Mostly, this is because of these Perl-like, cryptic features. There's no way of telling what those things do unless you're told. I find Python has a lot less of that kind of thing. On the other hand, it does mean that Ruby is a lot more concise and therefore much better for code golf :-)

    ReplyDelete