loading...
Cover image for Ruby Code Golf: Tips to Squash Character Counts

Ruby Code Golf: Tips to Squash Character Counts

jkvyff profile image Jens K Vyff ・3 min read

So you want to write succinct Ruby code that accomplishes magic in 40 characters, but maybe you can squeeze it down to just 39. This is the wonderful world of code golf. Write code that solves a problem in as few characters as possible.

Sorry linters and good code convention in general. But i'm trying to write a program that can sit in 50 Bytes of memory comfortably.

Get Rid of Bytes

Lets dive into a few common use cases where you could be doing the same work in fewer characters.

Methods

We are used to methods like this.

#(22 bytes)Beautiful, legible, and far too many bytes.
def add1(x)
    x + 1
end

#(15 bytes)Method name is now one char and we lost formatting.
def d x
x+1
end

#(12 bytes)You have probably used this compact form for a short method.
def d x{x+1}

#(10 bytes)But we can do better with a lambda object.
d=->x{x+1}

Note: Lambdas aren't called like other methods, you have the options:

  1. d.call(4) => 5
  2. d.(4) => 5
  3. d[4] => 5

So we save 2 bytes defining with lambda and variable
d=->x vs def d x
but we lose a byte for our shortest call
d[x] vs d x
The number of calls and variables in our program will change wether we use a method or lambda.

Looping

Quick tip: if assigning a parameter for your loops, it is often shorter though still valid to use < or > as opposed to ==.

There are many ways to create loops in ruby, but the most useful are:

  1. .map when altering data to container of the same size
  2. .times when one knows the number of times to perform a method
  3. .upto for cases where I would use a .times method on a string
#upto example
'1'.upto('3'){puts "cat"}
#or
'a'.upto('c'){puts "cat"}
> cat
> cat
> cat
=> nil

Printing

Ruby helps us out here as methods have an implicit return value, but that will not always be enough to get what we want. Upon seeing the output methods print, puts, and p it may seem like p is the obvious choice.

However, print, puts, and p are not alias' for one another and while p is a good choice to default to, sometimes it is faster to use one of the others if it's default output for your datatype is in the format you want.

#calls to_s on the object
print 1,2,3
> 123 => nil

#calls to_s on the object and newline after an element
puts 1,2,3
> 1
> 2
> 3
> => nil

#calls Also adds newline, but calls inspect, so you return the actual class of an object
p 1,2,3
> 1
> 2
> 3
> => [1, 2, 3]

Tip: Because of this, printing a symbol with print or puts instead of a string can save a byte.

Also useful in printing are the escape sequences for strings in double quotes.

  • \" – double quote
  • \\ – single backslash
  • \a – bell/alert
  • \b – backspace
  • \r – carriage return
  • \n – newline
  • \s – space
  • \t – tab

Extras

  1. Try t, *m, b = [1,2,3,4,5] if you want to use many parts of an array
    • t => 1
    • m => [2,3,4]
    • b => 5
  2. Save a byte
    • calling chars using a question mark like ?, instead of ','
  3. An alias for .join() is \* so d.join(',') could become d\*?,
  4. Use -[nil] or -[p] in place of .compact
  5. Check array uniqueness with a==a.uniq
  6. Find if character is included in an array
n = [1,2,3,4,5]
#(5 bytes)use the triple equals
n===3
> true

#shorter than the alternatives

#(11 bytes)
n.member? 3
> true

#(12 bytes)
n.include? 6
> false

Challenge

Using these techniques, I was able to get on the leaderboard of a fun golf challenge site. Beat my best if you can.

(Sorry code golf site for the double publish... forgot to put a name.)

Resources

https://codegolf.stackexchange.com/questions/363/tips-for-golfing-in-ruby?page=2&tab=Votes
https://medium.com/ruby-golf/ruby-golf-cheatsheet-eb27ec2cdf60
https://www.garethrees.co.uk/2013/05/04/p-vs-puts-vs-print-in-ruby/
http://golf.shinh.org/p.rb?pascal+triangle

Posted on by:

jkvyff profile

Jens K Vyff

@jkvyff

Student in a learning phase

Discussion

pic
Editor guide