What general tips can you give for golfing in Ruby?

I'm looking for ideas that can be applied to code golf problems in general that are specific to Ruby. (For example, "Remove comments" would not be an answer.)

Please post one tip per answer.

  • \$\begingroup\$ Someone needs to write a language called Rub, which uses a single Unicode character for every Ruby token, kinda like Jelly and Pyth :) \$\endgroup\$ – Mark Thomas Aug 30 '17 at 12:28

50 Answers 50


If the first line starts with #! and contains ruby, then Ruby will take command-line switches from it.

For example, if you require two libraries, you can golf



#!ruby -rbenchmark -rprime

which saves 7 bytes.

  • 4
    \$\begingroup\$ Or you can just add -rbenchmark -rprime to the character/byte count. That's usual in choice golf. \$\endgroup\$ – nyuszika7h Jul 5 '14 at 12:21

When getting input of fixed length the optional integer parameter to gets may come in handy.

  • Getting a substring:

    gets 10 vs gets[0,10] -- saves 3 bytes

  • Cutting trailing newline:

    gets 10 vs gets.chop -- saves 3 - log10(required_length) bytes (= 2 in this case)


<< trick

a.push x

can be shortened to:


for -4 bytes.

  • 2
    \$\begingroup\$ Note: this also works for Strings \$\endgroup\$ – Cyoce Nov 4 '16 at 1:13

To subtract one (-1), instead of doing this

(i - 1) * 2

do the following

~-i * 2

which will save you 2 bytes in cases where you otherwise have to use brackets (e.g. arithmetics).

  • 2
    \$\begingroup\$ like wise, (i+1) can become -~i \$\endgroup\$ – Cyoce Nov 4 '16 at 1:16

Re(ab)use predefined globals

There is a whole bunch of predefined global variables that you can use instead of initialising new variables.

A very common example is that you have some golfed one-liner that loops, but you also need to keep a counter for later:

s.gsub!(/../){i+=1;"foo"}while s=~/.../
p i

So frustrating. Luckily, $. comes to the rescue! It is initially 0, and is incremented each time you read a line from input. This is of course incredibly useful if you actually need to keep track of the amount of lines you have read, but otherwise you can just manually update it:

s.gsub!(/../){$.+=1;"foo"}while s=~/.../

That's 3 bytes saved.

If you for example need to append your counter to a string s, you may save some more bytes though string interpolation because the variable has a sigil:


Another interesting global is $:. It's an alias for $LOAD_PATH and is an array full of strings. I haven't actually used this in a golf yet, but I imagine it could come in handy if you need a cache for checking previously visited values or something, and don't care if it's completely empty. Your values are unlikely to crash with any of its initial contents anyways.


Save a byte when printing a word with symbols

This is a bit situational, but every byte counts!

puts"thing" # before
puts:thing  # after

Fun with arrays

There are many ways to do the same thing in ruby, and often times the default methods are inefficient - as a case study, a new arrays with set size and initialized to all 10:

Array.new(20,10) # idiomatic

You may already be informed not to use this syntax, however, when you are initializing elements in an array that needs to not be shallow-cloned, for example 2D arrays:

[[]]*20               # beware, all 20 elements points to the one same array
Array.new(20){[]}     # idiomatic
([0]*20).map{[]}      # free ticket, you can move any line into `0` to save newline
([a,b,c,d]*5).map{[]} # saves a char when you move 4 1-time use expressions

Many operations in ruby will create new objects. Sometimes this is to our advantage. For example, to create a new array with the same size as another array, we can get by without even knowing its .size at all:

[0]*a.size # looks kinda nice
a.map{0}   # -2 chars

(Note: the []* version may be preferable in cases where you also want to reuse the value, so [0]*b=a.size might end up helping you cut a char elsewhere)

To shallow clone an array:

b=a[0..-1] # makes sense
b=a*1      # this returns new_ary
b=*a       # this version for assignments - use [*a] in expressions
  • \$\begingroup\$ .clone is an alias of .dup ([*a] is still better for arrays) \$\endgroup\$ – Asone Tuhid Mar 1 '18 at 12:13

New features in Ruby 2.7 (experimental)

Ruby 2.7 is in prerelease (as of 17 Jun 2019) and has some features that look great for golfing. Note that some of them might not make it into the final 2.7 release.

All changes in Ruby 2.7-preview1: https://github.com/ruby/ruby/blob/v2_7_0_preview1/NEWS

Numbered block parameters

This is my favorite. It lets you finally drop the |a,b| in a block:

%w[a b c].zip(1..) { puts @1 * @2 }
# => a
#    bb
#    ccc

Method reference operator: .:

.: is syntactic sugar for the .method method, e.g.:

# => [(1/1), (1/2), (1/3), (1/4), (1/5)]

Pattern matching

I'm not sure how much use this will see in golf, but it's a great feature for which I only have a contrived example:

def div(*a)
  case a
    in [0, 0] then nil
    in [x, 0] if x > 0 then Float::INFINITY
    in [x, 0] then -Float::INFINITY
    in [x, y] then x.fdiv(y)

div(-3, 0) # => -Infinity

The pattern matching syntax has lots of features. For a complete list, check out this presentation: https://speakerdeck.com/k_tsj/pattern-matching-new-feature-in-ruby-2-dot-7

This is also the feature most likely to change before 2.7 is finished; it even prints a warning when you try to use it, which you should heed:

warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!

Beginless Range: ..3

Analogous to the endless Range introduced in 2.6, it may or may not have much use in golfing:

%w[a v o c a d o].grep(..?m)
# => ["a", "c", "a", "d"]

Enumerable#tally to count like elements

This could be useful in golfing:

%w[a v o c a d o].tally
# => {"a"=>2, "v"=>1, "o"=>2, "c"=>1, "d"=>1}

Enumerable#filter_map to filter+map in one

(1..20).filter_map {|i| 10 * i if i.even? }
# => [20, 40, 60, 80, 100]

If the block returns nil or false the element will be omitted from the result.

Integer#[] takes a range:

You've long been able to get a specific bit from an integer with with subscript notation:

n = 77 # (binary 01001101)
n[3] # => 1

Now you can get the value of a range of bits by passing two numbers or a Range:

n[2, 4] # => 3 (0011)
n[2..5] # => 3

New features in Ruby 2.5 and 2.6

Ruby keeps getting new features that look like they could be handy for golfing. Here are some that caught my eye. If there's any you think should be added feel free to edit or mention them in the comments.

(See also New features in Ruby 2.3 and 2.4.)

Ruby 2.5

Here's an easy-to-read reference with all of the new features in Ruby 2.5: https://rubyreferences.github.io/rubychanges/2.5.html

Regexp absence operator: (?~foo)

This matches any string that doesn't end with foo. I don't have a specific use for this one off the top of my head, but here's a good article about it.

Enumerable#all?, any?, none?, and one? accept objects that respond to ===

Similar to Enumerable#grep:

%w[Foo bar].one?(/[A-Z]/) # => true
%w[Foo bar].any?("bar") # => true
[1, 2, 3, 5, 7, 11].all?(0..10) # => false

Hash#slice gets a subset of a Hash

I don't see a lot of Hashes in Ruby golf, but it might come in handy:

{foo: 1, bar: 2, baz: 3}.slice(:bar, :baz) # => {foo: 1, bar: 2}

Ruby 2.6

All of the changes in Ruby 2.6: https://rubyreferences.github.io/rubychanges/2.6.html

Endless Range: 1..

Lots of potential uses for this.

%w[a b c].zip("X"..).to_a
# => [["a", "X"], ["b", "Y"], ["c", "Z"]]

[1, 2, 3, 5, 7, 11].any?(10..)
# => true

String#split takes a block

Saves four bytes when iterating over the result of String#split, e.g.:

"foo;bar;baz".split(?;).map {|s| x << s.upcase if ... }

You can do this:

"foo;bar;baz".split(?;) {|s| x << s.upcase if ... }

Note that it still returns the original string, so it won't always be fewer bytes than map.

Proc composition with >> and <<

Procs now have >> and << methods that let them be combined with other procs, or any object that responds to call:

double = ->n{ n * 2 }
square = ->n{ n ** 2 }
(double >> square)[5] # => 100
(double << square)[5] # => 50

% operator for Range

An alias for Range#step:

((1..10) % 2).to_a
# => [1, 3, 5, 7, 9]


Could be handy.

# => "'\xB2\xD7\ny"

When working with arrays, .compact can be replaced with -[nil] to save 2 chars.

  • 2
    \$\begingroup\$ -[p] saves another 2. \$\endgroup\$ – Doorknob Aug 25 '18 at 16:12

Use eval instead of reduce

While array.sum is great and shorter than array.reduce(:+), there are no similar methods for the other operators *, -, / ...

Joining arrays and evaling them saves some space:

a = [1,2,3,4]

a.reduce(:*)   # => 24
eval(a*?*)     # => 24
          ^^   two bytes saved.

It also removes the need to map string input to numbers first:

b = "1 2 3 4".split

  • 2
    \$\begingroup\$ eval a*?* to save another char. \$\endgroup\$ – Unihedron Jan 29 '18 at 6:31
  • \$\begingroup\$ also for case 2, using .tr' ',?* is way more concise than .split*?*... \$\endgroup\$ – Unihedron Jan 29 '18 at 6:33
  • 1
    \$\begingroup\$ also, note that a.reduce:* is valid if brackets aren't required though I think it can always be replaced with eval a*?* \$\endgroup\$ – Asone Tuhid Mar 1 '18 at 12:10

To check if a is an Array, instead of doing:


you can do


Won't work if a can be a string that contains [.

  • 4
    \$\begingroup\$ Or use the triple equals thing: Array===a ;) \$\endgroup\$ – daniero Jun 26 '15 at 23:33
  • 6
    \$\begingroup\$ How about a==[*a]? \$\endgroup\$ – histocrat Nov 4 '16 at 1:23
  • To generate symmetric output, you can use a single range like (-x..x) and then map a function on the absolute value: (-8..8).map{|x|x.abs}

  • Use short-circuit evaluation of boolean expressions to avoid if...else: x>1&&s+=x

  • To check if an integer array a contains a number x, you can use a-[x]!=a, especially useful if x is an expression.

  • Defining a variable as an accumulator is often shorter than using map and then reduce.

  • Use string interpolation with % for alignment: "x%12s"%?x is shorter than ?x+11*" "+?x or for base conversions: "%b"%65 vs 65.to_s(2)


Default function arguments

Pre-defining your variables within a function can save you from calling particular arguments if you already know what they are and are calling the function multiple times.

def f(a,b,c)
  return a+b+c
puts f(f(3,3,3),f(3,3,3),f(3,3,3))
# => 27

One can shorten this quite easily:

def f(a,b=3,c=3)
  return a+b+c
puts f(f(3),f(3),f(3))
# => 27

If you do not assign any second or third arguments, then b=3 and c=3 automatically. One can shorten this further:

def f(a,b=a,c=a)
  return a+b+c
puts f(f(3))
# => 27

Note however that you'll need to give it at least one variable, the first one, and I'm not quite sure how you can avoid assigning a value to b while assigning a value to c.

See here for more argument methods.


Is it an array?

Originally from histocrat.

Rather than writing

a.class==Array  # 14 bytes

you could write

a.is_a? Array   # 13 bytes

or even

a!=[*a]         # 7 bytes

Cloning strings

Strings are mutable in Ruby so if you have two variables holding the same string (a=b="string") and you modify one (a[0]="S"), the other will also change (b=="String")

To clone a string:


b=a.clone # 9 bytes
b=a.dup # 7 bytes
b=+-a # 5 bytes
b=-a # 4 bytes (b will be frozen)

Use ~// and !// to match against $_ (last line read)

These can be used with the -n or -p flags.

~/regex/ is equivalent to $_=~/regex/ returning the index of the first match or nil.

Try it online!

!/regex/ equivalent to $_!~/regex/ returning true or false.

Try it online!

Note that !// is weird as it doesn't call the ! method on the regex but only if you use a literal.

!/regex/ matches the expression.

r=/regex/;!r calls the ! (not) method and always returns false.

Also, !r=/regex/ gives an assignment in conditional warning so there's some syntactic sugar going on.


Quick way to check if all items in a Ruby array are unique lists various ways to check whether everything in an array is unique. Unfortunately, none of them are methods that I can send to a receiver, I need to have my array on both sides of an operator. Lame!

Fortunately, uniq! returns nil if no changes are made, and returns the modified array if changes are made, meaning that it can be placed at the end of a pipeline to check for uniqueness;

x.method1.method2.method3.uniq! ? "not unique" : "everything is unique!"

Various other shouty methods have similar behaviour - returning the modified array if changes are made and nil if no changes are made.


String split function uses $; or space by default; if input is space-seperated, you can omit the argument.

# Reads 3 integers from line 1 of input file
x,y,z=gets.split.map &:to_i

Or, you can configure the behaviour of ARGF with $/ (if there is only one line):

# Reads 3 integers from input file
# Not seperated by newlines, so in case of:
# 1 2
# 3 4
# You will get: 1 2 4 ("2\n3".to_i -> 2)
$/=' '
x,y,z=$<.map &:to_i

Due to the predictable behaviour of .to_i / .to_f, if you only have two numbers, you can use string.to_i(/.to_f) to get the first number and substring after the non-digit (even simpler for space) for the two values. There are tricks if you already know the constraints on the length of the numbers and especially so if the first one is length 1-2:

v=gets           # 1 2 / 11 22 / 11 22222222222222222222 / 123 4567890123456
v.to_i           # 1*    11*     11*                       123*
v[2,9].to_i      # 2*#$  22*#$   22222222                  3
v[2,99].to_i     # 2#$   22#$    22222222222222222222*#    3
v[2..-1].to_i    # 2#    22#     22222222222222222222*#    3
v[/\d+$/].to_i   # 2     22      22222222222222222222      4567890123456
v[~/ /,9].to_i   # 2$    22$     22222222                  45678901
v[~/ /,99].to_i  # 2     22      22222222                  4567890123456*
v[~/ /..-1].to_i # 2     22      22222222                  4567890123456

*: recommend to use in cases as specific than this
#: 1st int in string length is expected to be <=2 (-10 < x < 100)
$: 2nd int in string length is expected to be <=8 (if 1st int is length 1: <=9)
Note: [x,99] will take 99 characters, while ..-1 goes all the way to end of string. Because ~/ / matches the index of the space, this should be accounted for: [~/ /,9] will get length 8 int at most, as first char is the space
Note: If there are three+ numbers, please just use split or map

The above trick can be combined with $_:

p *gets.to_i..$_[2,9].to_i

Handy ways to repeat strings:

# aaaaabcbcbcbcaaaaa,aaaaa,aaaaa

Shorthand for size of input line:

p (eval gets.chars*?+)/~/$/
# is equivalent to:
p (eval gets.chars*?+)/$_.size

The <=> (spaceship) operator compares two expressions and returns -1, 0, or 1. Applies to anything that can be compared with <, >, and ==.

Some example uses:

x<=>0 is equivalent to the sign function.

x.*x<=>0 is the absolute value of x.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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