May 05 2015

Why we have routine "code challenges".

Software engineering is a craft like any other, one that requires maintaining a sharp set of tools at all times. While software engineers may not work with saws and chisels, they do work consistently with their minds and thought patterns.

In an effort to aid our engineers in maintaining a sharp toolset, here at MojoTech we have routine “code challenge” exercises that are given to the team. These challenges are given as a fun change-of-pace exercise and each challenge offers a varying degree of difficulty.

The MojoTech engineering team is made up of very varied backgrounds. We have engineers with degrees in English, Psychology, Photojournalism as well as the more traditional Computer Science and Math backgrounds. This type of diversity is excellent from a personnel level, but it also means that some engineers may lack experience with more formal engineering algorithms and theories. The "code challenge" exercises also work to help fill in any of these potential knowledge gaps.

Each code challenge varies in difficulty level and technical approach, and provides an opportunity for each engineer to solve a problem using any programming language they desire.

Some engineers may show an interest in getting better at functional programming and choose to solve a challenge in say Clojure or Haskell, while others may feel proficient in scripting language but want to get better at typed languages, and therefore choose to solve a challenge in Go or PureScript.

Recent challenges have included implementing an algorithm to play the game of Nim successfully, counting all possible combinations of coins that allow a given denomination of change to be made, or decoding a secret phrase based on an input of triplets.

Sometimes as engineers, it becomes easy to neglect what may seem like "the basics" because we feel as if we deal with much more complex problems all the time. However, it is important to note that, more often than not, solving "complex" problems really is just a matter of solving a series of smaller, less complex problems first.

A recent example of a simple challenge we did is as follows:

Write a function ho() that has the following return value pattern:
ho(); // should return "Ho!"
ho(ho()); // should return "Ho Ho!"
ho(ho(ho())); // should return "Ho Ho Ho!"
More details:
* each call to ho() must add a "Ho" to the string
* the "Ho"'s must be separated by a space
* at the end of the string, there must be an exclamation mark !, without a space

This is a seemingly simple exercise, but there are a number of ways to solve it in any given language. Let's take a look at some JavaScript solutions first:

function ho() {
return arguments[0] ? 'Ho ' + arguments[0] : 'Ho!'
}
function ho(p) {
return p ? "Ho " + p : "Ho!"
}
function ho(e) {
return e ? "Ho ".concat(e) : "Ho!"
}
function ho(p) {
if (!p) { return "Ho!"; }
return p.replace(/!/g, ' ') + "Ho!"
}

All four of these solutions work perfectly well, but which is the "best" or which is the most performant? Think you know? Take a look at the jsperf runs and see if you were right or wrong.

Likewise with Ruby, which is best?

def ho(s=nil)
s.nil? ? "Ho!" : "Ho #{s}"
end
def ho(a=nil)
a ? "Ho #{a}" : "Ho!"
end
def ho(current_string = nil)
"#{current_string ? "#{current_string[0..-2]} " : ''}Ho!"
end
def ho(current_string = '')
hos = current_string.split(' ').unshift('Ho').join(' ')
hos.include?('!') ? hos : "#{hos}!"
end
def ho(h = '')
h.gsub(/!/, ' ') + "Ho!"
end
def ho(hos = nil)
if hos
"Ho #{hos}"
else
'Ho!'
end
end
def ho(str = nil)
str ? "#{str[0..-2]} Ho!" : "Ho!"
end
def ho(e = nil)
e.nil? ? "Ho!" : e.insert(0, "Ho ")
end

What about implementation differences in Go, Clojure, Rust, Haskell, Python, etc...?

While we don’t set a firm time deadline when each challenge is released, after a week or so we do begin to post solutions for the whole team to review.

All solutions for a given language are benchmarked against each other and posted for review by the rest of the engineering team. This allows engineers to see alternative approaches to solving a particular problem that they may not have thought of before, as well as provide metrics on how performant or not a particular solution may be. Engineers are then able to leverage this new knowledge on current and future client projects.

If you enjoy problem solving and continually sharpening the tools in your toolbox, come join us at MojoTech.

Craig P Jolicoeur

Share: