Learn By Do. Part III

This is kinda like a bumper edition, since it wasn’t intended but after hacking this for a bit, it turned out to be a pretty useful exercise, no matter the language. Why? Primarily since you get to, depending on implementation, write your own data structures and use recursion. This combination of tasks usually allows you to explore and discover some interesting language-related issues. So then, without further ado.

The task: generate all the possible word combinations from a telephone number. The first stab, ignore dictionaries and words or phrases that actually make sense in English, and just be able to “translate” the number 23 => ad, ae, af, bd, be, bf, cd, ce and cf. If the number is 233, the options become add, ade, adf, aed, aee, aef and so on all the way through to cff. And then later maybe we can reverse the process and make up a word to come up with a number?

Right, the strategy: write tests first! The first thing i need is a class that can accept and validate a string as being a legit phone number.

class TestPhoneNumber < Test::Unit::TestCase
  def test_ctor
    p ="0215556767")
  def test_cant_have_alpha
    assert_raise(ArgumentError) {"065a223")}
  def test_cant_have_punctuation
    assert_raise(ArgumentError) {"087!322")}
  def test_cant_have_other
    assert_raise(ArgumentError) {"0987%")}
  def test_split_numbers
    p ="0123")
    assert_equal(["0", "1", "2", "3"], p.split_numbers)

I also wanted to store the individual digits since in my mind’s eye, i can see myself using a map to index and reference the letters using the digits so it just feels like something i need to do right now. We’ll see how it plays out. Turns out, the implementation is pretty straightforward:

def initialize(number_as_string)
   if number_as_string =~ /\D/
     raise"Can only contain numbers")
   @split_numbers = split_the_numbers(number_as_string)

A simple regular expression takes care of most of what i need to cover. Splitting the numbers is a simple loop, no fuss there.

def split_the_numbers(numbers)
  i = 0
  result = [""]
  while i< numbers.length
    result[i] = numbers[i,1]; i += 1
  return result

The trick now is to be able to write something like:"23").possible_words.each do {|word|
 print word

And get the output:


Mmmm… Tree? Graph? Simple arrays and hashes? What will it be? (…to be continued)


Learn By Do. Part II

In the first installment, we discovered, from the eyes of a noob, a handful of basic concepts about the Ruby language. In this episode, we’ll complete the functions for mean, median, variance and hence standard deviation and discover something you might consider magic…

The mean. It’s the average and so it’s calculation is simple. Add up all the elements and divide by the number of elements. The sum:

    @sum = 0.0
    @elements.each{ |i| @sum += i }

The mean:

  def mean
    if 0 == @elements.length
      return 0
    return @sum / @elements.length

Straightforward and fairly clean. The median is also pretty straightforward; you want the middle element, in the case of an odd-numbered quantity and the average of the middle elements in the case of an even-numbered quantity.

  def median
    if 0 == @elements.length
      return 0
    if 0 == (@elements.length % 2)
      return even_median
      return odd_median

I used the modulus operator to determine if the quantity of elements is odd or even, and it’s pretty much the same as almost every other language i’ve used. There is another way, using the remainder method:
any_even_number.remainder(2) is equal to 0
any_odd_number.remainder(2) is equal to 1
The even/odd_median methods just return the appropriate middle element. First the odd_median:

  def odd_median
    return @elements[(@elements.length/2).floor]

It might seem a little odd, at first, to not use the calculation (n+1)/2:

return @elements[(@elements.length + 1 )/2]

The reason we use the floor is because we know the number of elements divided by 2 will always yield a n.5 and we take the index down form that because we’re using a ZERO-based index in the array. (n+1)/2 works perfectly for a ONE-based index array. We could still use that approach however, but keeping in mind to subtract 1 from the result to get the correct index: ((n+1)/2) -1.

  def even_median
    top = @elements.length/2;
    bottom = top -1
    agg = @elements[bottom] + @elements[top]
    return agg / 2.0

Again, because we’re working with ZERO-based index arrays, the calculations are slightly different to what you’d expect or do in “normal mathematics” (if there can ever be such a term?). Easy, peasy, japaneasy, right?

Variance is a slightly more complicated, although, not complex by any stretch of the imagination. There are two different algorithms for calculating the variance and in the provided code, i have implemented both. Armed with the knowledge of the equations and a decent grip on how to perform some calculations, the implementation is left to you as an exercise in applying your learning.

The magic. At last, the magic. (from Ruby-coloured glasses)

class Float
  def prec(x)
    mult = 10 ** x
    return (self * mult).truncate.to_f / mult

The almost crazy thing happening here is that you have the ability to extend built-in types without much fuss. With this definition, you now have the prec method available to all your Floats. Try it in your console too.

irb(main):006:0> class Fixnum
irb(main):007:1> def plus10
irb(main):008:2> return self + 10
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0> 43.plus10
=> 53

Now that’s cool. Strings, Times, Fixnums, Floats… If your domain requires a specific handling on a particular type; the ability to extend and make that appear “normal” for the remainder of the coding experience is easy. It just slides right in.

And that about wraps up Part II, save one small little detail you’ll find in the code but not elaborated just yet: the accessor. The Ruby User’s Guide has a great explanation, and now you also know about that website too!

The full source code for Learn By Do is available for download: sample_data.rb


Learn By Do. Part I

If you want to learn to code, the best way is to code… lots. No getting around it, and for me, my fingers seem to remember more than my brain. So keeping that in mind, here begins a short series of code snippets and samples which i’ve used to help myself learn the Ruby language. Hopefully, this helps you out a little as well as you start exploring the language for yourself. Of course, a lot of the information is also gleaned from around the web. I’ll endeavour to give credit where it’s due, if i forget or leave anyone out, it’s not intentional. Please feel free to prompt me a kind “ahem”. And also, i ain’t no matter expert, so if you spot an inefficiency somewhere, i’d appreciate a little pointer too. Thank you.

So, the key things that i want to learn are:
* language syntax
* keeping with lessons learned in oop
* how to write/test logic

And then of course, i also want to write something relatively “useful”. Not some imaginary and contrived Product-Catalogue relationship or Animal, Dog, Cat hierarchy, thank you very much.

That’s it, really. So essentially i want to capitalize on the two main languages i’ve spent a lot time in and what they taught me: C++ => OO principles, and then C++/C# => TDD. Armed with the basics, i, and by extension that is, you too, can pretty much tackle just about any problem within my (your) comprehension.

So the first challenge is writing a class that can handle finding the mean, median, variance and standard deviation for an array of numbers (integers or floats). Fits all my criteria and will certainly help me determine and check answers while i study through my courses at uni. That is to say, it’s very useful for me. So, with further ado…


require ‘test/unit’ at the top of your file and inherit from Test::Unit::TestCase.
If you’re familiar with TDD in general and been exposed to xUnit frameworks, that’s about all you need to know, the rest is straightforward.
So i want to test my new class SampleData which is initialized with an array of numbers and sports three basic methods: mean, median and variance (for now). The first thing i did was create TestSampleData

class TestSampleData < Test::Unit::TestCaseend

First task; make sure you can’t declare without passing in an array of numbers; that is, i want to force usage to always supply an array of numbers when you construct it. Hey, it’s my design so i get to choose the why.

class SampleData
  def initialize()
  def initialize(elements)

Almost like C++, the public and private sections of the class definition are straightforward. Nothing tricky there. Now i’m forced to, at minimum declare instances with a parameter:[]). It’s what i wanted.

Next concern was making sure the parameter passed in is what i expect it to be (defensive programming). Make sure it’s an array of either Fixnum or Float. If it’s not, i want the constructor to raise an exception.
The exception is the easy bit:


. Checking the type of the parameter is also easy with the class method.

  def initialize(elements)
    if Array != elements.class
      raise"Can only initialize sample data with an array of floating points or integers")

And then checking the type of each element in the array also turns out to be pretty straightforward

    elements.each do |e|
      if (!(Fixnum == e.class) || (Float == e.class))
        raise"Array can only contain floating points or integers: item " + e.to_s + " is a " + e.class.to_s)

Of course, all this is verified with a bunch of tests declared by the test case:

  def test_must_init_with_array
    assert_raise(ArgumentError) {"string") }
  def test_must_init_with_array_of_numbers
    assert_raise(ArgumentError) {['ll', 'llkj']) }
    assert_raise(ArgumentError) {[0, 8, 'll', 9, 7, 'llkj']) }

The code reads for itself. All i need to do to verify is, from the commandline, run ruby filename.rb.

bryan@noah:~/src/sandbox/ruby/medians$ ruby sample_data.rb
Loaded suite sample_data
Finished in 0.002402 seconds.

6 tests, 16 assertions, 0 failures, 0 errors

That’ll do it for Part I. Key things learned:
* public, private sections of a class definition and the syntax thereof
* writing a test case
* raising exceptions, and testing for expected exceptions
* checking types and forcing class usage
* a little tight looping and boolean logic

So far so good, and really nothing too different or difficult to grasp coming from either C++/C#. Part II to follow shortly…