Uncategorized

Performing Exercism on Ruby!

One day I stumbled upon this awesome site called “Exercism”. It mainly focuses on improving your skills via Deep Practice & Crowdsourced Mentorship, Strengthening your problem-solving skills by guiding others through the process. I got hooked onto it and then I thought why not share my learning with all. Being a Ruby programmer, my notes are Ruby based.

Things To Keep In Mind

Before tackling any program/problem/challenge you should keep certain points in your mind. Some are general, some are more language specific.

Some questions you might want to ask yourself:

  1. Am I adhering to the Single Responsibility Principle?
  2. Is all my code on the same abstraction level?
  3. Can I combine conditional clauses?
  4. How does my API look to clients of this code (i.e. how do other classes interact with this class)?
  5. Do I have duplication?
  6. What requirements are likely to change? Would I be able to implement such changes painlessly? [Note that it is not that you should normally guess what future requirements are, but it can be helpful on Exercism]

Use Private, that way you limit the public API of any class. It’s considered a good practice to expose as few methods as possible, so you don’t come up with a “fat interface” and has to maintain a lot of methods that probably nobody else uses (this is troublesome when you want to refactor your code but you aren’t sure if somebody is using method x or not.

If you are using in-built methods you should understand them first – how they work, what are the pros & cons, in which use-case you should use them. Don’t assume, dig them up. Some examples:

  • p & puts are not the same
    p foo does puts foo.inspect , i.e., it prints the value of inspect instead of to_s, which is more suitable for debugging (for example, you can tell the difference between 1, “1” and “2\b1”, which you can’t when printing without inspect).
  • to_a  is super-expensive on big ranges.
  • Use string interpolation only when necessary.
  • a.map(&:to_i) i.e. Symbol#to_proc  : you are passing a reference to the block (instead of a local variable) to a method. Also Symbol class implements the to_proc method which will unwrap the short version into it’s longer variant. Example:

Some problems from Exercism

I have described what I learned from individual problem. I am also putting names of the relevant problems so that you can look them up. My code is uploaded on Github. Also I have explained why I used certain in-built Ruby methods. I have highlighted some specific things that you should consider in general.

Accumulate

Two ways to yield a block in ruby : yield & call

(Read “ZOMG WHY IS THIS CODE SO SLOW?”)

  • Yield returns the last evaluated expression (from inside the block). So in other words, the value that yield returns is the value the block returns.
  • If you want to return an array use map/select depending on situation. You don’t need to initialize an array & return it.

Anagram

Anagrams are same if sorted.

select  will return element if condition satisfies. So in case of conditions use select  over map / each .

Beer-songs

Follow this link

Binary

Use map.with_index  so that you do not have to initialize another variable & directly apply  inject on the result.

Bob

Start simple. Try to make test pass in a very easy way.

Etl

Use of each_with_object :

Grade-school

Initialize an empty hash and declare values as an array. To sort & return a hash use hash.sort.to_h .

Grains

Sometimes solution could be a single word. Check for patterns. For instance, here you don’t have to iterate 64 separate calculations in self.total. Think about the totals for the first few squares: 1, 3, 7, 15, 31. Now think about those totals in relation to powers of two. Total is a series of (2x-1) where x is 2**(n-1).

Hamming

  • raise  could be another method. Always look out for single responsibility principle.
  • select  &  count  are perfect methods here.
  • It is considered a good practice to expose as few methods as possible, so you don’t come up with a “fat interface” and maintain a lot of methods that probably nobody else will use. This is troublesome when you want to refactor your code but you aren’t sure if somebody is using that method or not. In this exercise, the only method being called is self.compute , so this means you could make self.raise_size_mismatch  private and avoid exposing it.

Hello-world

You can pass default argument to a Ruby method :

Leap

You can minimize loop:

to:

But I won’t prefer it, because the former one is more readable. Sometimes you have to gauge which is worthier.

Phone-number

Interesting use of sub:

Raindrops

Assign common values as constant. Avoid unnecessary computing. For example you only need to check if 3, 5 & 7 are factors.

Robot-name

shuffle  method of Array (can be applied to a-z but will be futile for 0-999 as it takes lots of memory & computation). Use Default assignment  ||=

 

That’s it for now. Please do let me know how this blog helped you and whether I missed something that should be included. Sayonara for now!

Leave a Reply

Your email address will not be published. Required fields are marked *