Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

What general tips do you have for golfing in Ruby? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to Ruby (e.g. "remove comments" is not an answer). Please post one tip per answer.

-- borrowed from marcog's idea ;)

share|improve this question
add comment

12 Answers

up vote 18 down vote accepted
  • The numbers 100 to 126 can be written as ?d to ?~ in 1.8.
  • On a similar note if you need a single-character string in 1.9 ?x is shorter than "x".
  • If you need to print a string without appending a newline, $><<"string" is shorter than print"string".
  • If you need to read multiple lines of input $<.each{|l|...} is shorter than while l=gets;...;end. Also you can use $<.read to read it all at once.
  • If you're supposed to read from a file, $< and gets will read from a file instead of stdin if the filename is in ARGV. So the golfiest way to reimplement cat would be: $><<$<.read.
share|improve this answer
    
?x yields the ascii code in general, so you can realistically get all the printables to digits in two characters. 1.9 is different, 'a'.ord yields the ascii number, but is four bytes longer than the decimal version. –  Hiato Feb 3 '11 at 8:03
    
You can use ?a.ord in 1.9, but that's still longer than the decimal. –  Nemo157 Feb 3 '11 at 22:59
1  
An even golfier way to implement cat is to leave the ruby file completely empty (0 bytes) and insist that it should be run from the command line with the -p flag. –  daniero Jul 17 '13 at 20:01
add comment

Use the splat operator to get the tail and head of an array:

tail, *head = [1,2,3]
tail => 1
head => [2,3]

This also works the other way:

*head, tail = [1,2,3]
head => [1,2]
tail => 3

Use the * method with a string on arrays to join elements:

[1,2,3]*?,
=> "1,2,3"
share|improve this answer
add comment
  • Use abort to terminate the program and print a string to STDERR - shorter than puts followed by exit
  • If you read a line with gets, you can then use ~/$/ to find its length (this doesn't count a trailing newline if it exists)
  • Use [] to check if a string contains another: 'foo'['f'] #=> 'f'
  • Use tr instead of gsub for character-wise substitutions: '01011'.tr('01','AB') #=> 'ABABB'
  • If you need to remove trailing newlines, use chop instead of chomp
share|improve this answer
    
+1 for abort and ~/$/ –  J-_-L Jun 26 '11 at 22:13
add comment

Use the short predefined variables wherever possible, e.g. $* instead of ARGV. There's a good list of them here, along with a lot of other useful information.

share|improve this answer
add comment

Scientific notation can often be used to shave off a char or two:

x=1000
#versus
x=1e3
share|improve this answer
5  
Note: This will return a Float value (1000.0) instead of an Integer, which may cause inaccurate results with large numbers. –  Dogbert Feb 25 '11 at 11:02
1  
Ah, nice 1e2 is better than 100.0 when a percentage is needed. –  Phrogz Feb 26 '11 at 6:36
add comment

$_ is last read line. Also you have methods in Kernel that operate on $_:

  • chop
  • chomp
  • sub
  • gsub
  • print - if no argument given print content of $_

If you want to print some variable often then use trace_var(:var_name){|a|p a}

share|improve this answer
    
These are only available when you run Ruby with the -p or -n option. Reference. –  Darren Stone Dec 27 '13 at 19:12
add comment

If you need to find if a particular element e is inside a range r, you can use

r===e

instead of the longer:

r.cover?(e) # only works if `r.exclude_end?` is false

or

r.member?(e)

or

r.include?(e)
share|improve this answer
2  
Isn’t r===e even shorter? –  akuhn Jun 1 '12 at 21:10
    
@akuhn Yes, it is. Much Shorter. Thanks for pointing that out, it helped me shorten my code by 10 chars, which is huge: codegolf.stackexchange.com/a/6125/3527 –  w0lf Jun 1 '12 at 21:20
    
You’re welcome. Everything that can be used in a switch statement has === implemented. –  akuhn Jun 2 '12 at 12:49
add comment

Use Goruby instead of Ruby, which is something like an abbreviated version of Ruby. You can install it with rvm via

rvm install goruby

Goruby allows you to write most of your code as you would be writing Ruby, but has additional abbreviations built in. To find out the shortest available abbreviation for something, you can use the helper method shortest_abbreviation, for example:

shortest_abbreviation :puts
#=> "pts"

Array.new.shortest_abbreviation :map
#=> "m"

String.new.shortest_abbreviation :capitalize
#=> "cp"

Array.new.shortest_abbreviation :join
#=> "j"

Also very handy is the alias say for puts which itself can be abbreviated with s. So instead of

puts [*?a..?z].map(&:capitalize).join

you can now write

s [*?a..?z].m(&:cp).j

to print the alphabet in capitals (which is not avery good example). This blog post explains more stuff and some of the inner workings if you are interested in further reading.

PS: don't miss out on the h method ;-)

share|improve this answer
add comment

Build arrays using a=i,*a to get them in reverse order. You don't even need to initialize a, and if you do it doesn't have to be an array.

share|improve this answer
add comment

Use || instead or and && instead and.

Beside the one character from and you can save the spaces (and perhaps the bracket) around the operator.

p true and false ? 'yes' :'no'   #-> true (wrong result)
p (true and false) ? 'yes' :'no' #-> 'no'
p true&&false ? 'yes' :'no'      #-> 'no', saved 5 characters


p true or false ? 'yes' :'no'   #-> true (wrong result)
p (true or false) ? 'yes' :'no' #-> 'yes'
p true||false ? 'yes' :'no'      #-> 'yes', saved 4 characters

If you loop on an array you normally use each. But map loops also over an array and it is one character shorter.

share|improve this answer
add comment

Use p var instead of print var.

share|improve this answer
5  
Unfortunately p 'some string' prints "some string" and not just some string which is often criticised by others. –  padde Jun 1 '13 at 21:11
add comment

I just attempted a TDD code-golf challenge i.e. Write shortest code to make specs pass. The specs were something like

describe PigLatin do
  describe '.translate' do
    it 'translates "cat" to "atcay"' do
      expect(PigLatin.translate('cat')).to eq('atcay')
    end
    # And similar examples for .translate
  end
end

For the sake of code-golf, one need not create a module or class.

Instead of

module PigLatin def self.translate s;'some code'end;end

one can do

def(PigLatin=p).translate s;'some code'end

Saves 13 characters!

share|improve this answer
    
Ha, very thorough. Not only did you add the necessary behavior to PigLatin, but also to @pig_latin, $pig_latin, and 'pig'['latin']. –  histocrat Feb 27 at 15:23
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.