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?

Use Private, that way you limit the public API of any class. It is 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).
name = ‘Anjali Jaiswal’puts “Welcome #{name}”

# Example where string interpolation is not needed

puts ‘Hello World!’
  • 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:
a = [“2”, “3”]a.map(&:to_i) # a(&:to_i.to_proc)#=> a = [2, 3]

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

# yield statementdef speak  yieldend# call statementdef speak(&block)  puts block.callend

(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.

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 :

input.each_with_object({}) do |(score, letters), result|  letters.each do |letter|     result[letter.downcase] = score  endend

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.

HELLO-WORLD

You can pass default argument to a Ruby method :

def hello(name = ‘world’)  #some dataend

LEAP

You can minimize loop:

if year % 4 == 0 && year % 100 == 0  year % 400 == 0 ? true : falseelsif year % 4 == 0  trueelse  falseendto:year % 400 == 0 || year % 4 == 0 && year % 100 != 0

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:

‘0987654321’.sub(/(\d{3})(\d{3})/, “(\\1) \\2-”) # will result in “(098) 765–4321”# Can return a part of string like:‘0987654321’[0..2] # will result in ‘098’

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!

Programmer, avid Reader, artist, exploring different trades, fun-loving, adventurous and most of the time a hell-yes person!