Oct 25, 2005

World X I Selectors....Were you listening?

In the recently held ICC Super Series, World XI was thrashed, beaten to pulp by the aussies in both one day series and super six day test match which ended in 3 days :-) or were the ICC planning for 2 super test matches..ahahha

So ICC thought..hey lets bring 11 world best players..and then they should just appear on the ground and success will be theirs..Aussies will be humbled on their homeground after being beaten fair and square (no debates here please) by English in the earlier concluded Ashes..

But..wink wink..we get the opposite..The big giants..are brought to their knees...Knock knock..why..The Selectors missed the big factor..The "TEAM" factor..Can these 11 stars play as 11 close knit, well informed, aware of each other, trusting, communicating members of a well oiled team..The thing they must have looked for is can we bring 11 above average players from non Aussie teams, see how they can gel, how much time would that take and then pitted them against the Aussies...That would have surely been more brilliant than Eng Vs Aus 2005 or Ind vs Aus 2001 series...2 very famous closely and hard fought test series...

So alls gone down the wind..ICC does best what they can now..they see no ICC super series...so it means you blame the players and everything else but your abiltity to pick the right players..ICC doesnt want to learn..I think...No wonder the game is being held togehter by a few wonderful unselfish players on each team...

Lesson for us: The team's only goal is to succeed, not to have A star team which can figure out how to win and thats what Scott says here in this wonderful essay...

The myth of all star teams

All-star teams lose. While it’s an honor to be chosen to an all-star team, it’s miserable to play on one. These teams are constructed without consideration for how to bring people together. Whenever an all-star team plays a mediocre, but intact team, they usually lose.
Read this and apply to World X1 team and it looks like Scott saw the matches and then wrote the article..But then where ever teams are expected to win these rules laid down in the essay apply..
------Scott Berkun

Looks like Scott saw the matches and wrote the essay..But then this applies to all teams...Great essay..Must read..highly recommended..

Oct 20, 2005

I am Impressed. Mighty Impressed

On an earlier post I had mentioned that I will be comparing EzExpense java application by rewriting it in Ruby. But I thought let me start at a smaller scale and I went back to my numerology application.

Let me explain the application domain:

I meet a numerologist Janjay Sumani . He wants an application for the following. People come to him for advice on numbers. Given a person's name and birth date he computes some numbers and tells them what numbers they belong to, what are lucky, unlucky blah blah. Note by this I dont expect anyone to believe in numerology nor does the blogger.

Back to business I ask him give me an example : He says lets start with u.

Ur name: Deepak Manharlal Surti and Date of birth : 24 May 1977

He says we have a letter-number chart which tells the numeric value of each letter. We subsittue that for each word in a name. So Deepak => 455812. Now we find sum of digits : 455812 = > 25 => 7. Here he gives me a caveat: If the number is any of 11 , 22, 33, 44, 55, 66, 77, 88, 99 we dont reduce.

So lets do the calcs for Deepak Manharlal Surti
=> 455812 415512313 36241
=>25 25 16
=>7 7 7

So 21 is higher name number. Reduce 21 =>3 gives me lower name number. Haa now I understand I say.

Next we pick the birht date:
24 May 1977
=> 24 5 1977
=> 6 5 24
=> 6 5 6
=> 17

So 17 is my higher destiny number and 8 is my lower destiny number.

And just take the day you were born. 24. So 24 => 6 are my higher and lower material numbers respectively.

I start with app development using TDD (Test Driven Development) style and here's what I get:

I had written that app in Java with a web interface and a domain model. The classes in the domain
model were:

  • NumerologyCalculator.java (80 lines)--This was the central class. It calculated numbers.
  • NameManipulator.java (41 lines) -- This was to split a name into individual parts (viz Deepak Surti is split into [Deepak, Surti])
  • Letter.java(19 lines) -- A final class to hold letter values. A has value 1, D has value 4 etc in numerology. To look up these values.
  • DateGenerator.java(28 lines) -- A class to generate dates given a string. Note I didnt use java's Date class it was too complicated for my app. I instead created a custom MyDate class which comes next. Here i just need mth, year, day.
  • MyDate.java (31 lines) -- This had no responsibility. Its just a java bean.
  • UserInfoBean.java (84 lines) -- This was just a bean to hold user info viz his name, date and numbers.
Now lets add up . We get 283 lines of domain model code. Just to calculate numbers for a person given his name and date.

Further there was test code. Unit test which was 128 lines for the main TestNumerology.java. Here I tested only 6 birth dates and 3 names which I can say is not extensive coverage.
There were other test classes for other domain model objects which we ignore.

See all domain model code: Though its much better than procedural Java code that I have written in the past :-(( and thankfully have given up where I can, this code is still way 2 different from real business logic. How I wish my domain code and the business sat naturally with each other. That is if I could write code which read so much like the business. Anyways the code for u to see:

package com.deepaksurti.numerology.calculate;

import junit.framework.*;
import java.util.*;

import com.deepaksurti.numerology.calculate.BirthDate;
import com.deepaksurti.numerology.calculate.NumerologyCalculator;

* Created by IntelliJ IDEA.
* User: Deepak Surti
* Date: Dec 10, 2001
* Time: 10:14:55 PM
* To change this template use Options | File Templates.
public class TestNumerology extends TestCase{
NumerologyCalculator _calculator;
private BirthDate _birthDate1;
private BirthDate _birthDate2;
private BirthDate _birthDate3;
private BirthDate _birthDate4;
private BirthDate _birthDate5;
private BirthDate _birthDate6;
private String _name1;
private String _name2;
private String _name3;

protected void setUp() {
_calculator = new NumerologyCalculator();
_birthDate1 = new BirthDate(24, 5, 1977);
_birthDate2 = new BirthDate(14, 5, 1977);
_birthDate3 = new BirthDate(4, 5, 1977);
_birthDate4 = new BirthDate(24, 11, 1977);
_birthDate5 = new BirthDate(24, 12, 1977);
_birthDate6 = new BirthDate(28, 3, 1977);
_name1 = new String("Deepak Manharlal Surti");
_name2 = new String("Shilpa Pratap Shinde");
_name3 = new String("Manhar Balubhai Surti");

public void testMaterialNo() {
int material_no;

material_no = _calculator.calculateMaterialNo(_birthDate1);
assertEquals(material_no, 6);

material_no = _calculator.calculateMaterialNo(_birthDate2);
assertEquals(material_no, 5);

material_no = _calculator.calculateMaterialNo(_birthDate3);
assertEquals(material_no, 4);

material_no = _calculator.calculateMaterialNo(_birthDate6);
assertEquals(material_no, 1);

public void testHigherMaterialNo() {
int higherMaterialNo;

higherMaterialNo = _calculator.calculateHigherMaterialNo(_birthDate1);
assertEquals(higherMaterialNo, 24);

public void testDestinyNo(){
int destiny_no;
destiny_no = _calculator.calculateDestinyNo(_birthDate1);
assertEquals(destiny_no, 8);

destiny_no = _calculator.calculateDestinyNo(_birthDate4);
assertEquals(destiny_no, 5);

public void testHigherDestinyNo() {
int higherDestinyNo;

higherDestinyNo = _calculator.calculateHigherDestinyNo(_birthDate1);
assertEquals(higherDestinyNo, 17);

higherDestinyNo = _calculator.calculateHigherDestinyNo(_birthDate4);
assertEquals(higherDestinyNo, 23);

public void testMonthNo() {
int month_no;

month_no = _calculator.calculateMonthNo(_birthDate1);
assertEquals(month_no, 5);

month_no = _calculator.calculateMonthNo(_birthDate4);
assertEquals(month_no, 11);

month_no = _calculator.calculateMonthNo(_birthDate5);
assertEquals(month_no, 3);

public void testYearNo() {
int year_no;

year_no = _calculator.calculateYearNo(_birthDate1);
assertEquals(year_no, 6);

public void testNameNo() {

int name_no;

name_no = _calculator.calculateNameNo(_name1);
assertEquals(name_no, 3);

name_no = _calculator.calculateNameNo(_name2);
assertEquals(name_no, 5);

name_no = _calculator.calculateNameNo(_name3);
assertEquals(name_no, 1);

public void testHigherNameNo() {
int higherNameNo;

higherNameNo = _calculator.calculateHigherNameNo(_name1);
assertEquals(higherNameNo, 21);

higherNameNo = _calculator.calculateHigherNameNo(_name2);
assertEquals(higherNameNo, 14);

higherNameNo = _calculator.calculateHigherNameNo(_name3);
assertEquals(higherNameNo, 19);



package com.deepaksurti.numerology.calculate;

import com.deepaksurti.numerology.calculate.BirthDate;

import java.util.Collection;
import java.util.Iterator;

* Created by IntelliJ IDEA.
* User: Deepak Surti
* Date: Dec 22, 2001
* Time: 9:34:16 AM
* To change this template use Options | File Templates.
public class DateGenerator {
public static BirthDate generateBirthDate(String date) {
Collection splitUpDates = NameManipulator.locateWordsInName(date);
Iterator it = splitUpDates.iterator();
int dates[] = new int[3];
int index = 0;
while(it.hasNext()) {
String next = (String)it.next();
if(next.equals("")) dates[index++] = 0;
dates[index++] = (new Integer(next)).intValue();
return new BirthDate(dates[0], dates[1], dates[2]);


package com.deepaksurti.numerology.calculate;

import java.util.HashMap;

* Created by IntelliJ IDEA.
* User: Deepak Surti
* Date: Dec 20, 2001
* Time: 12:57:55 PM
* To change this template use Options | File Templates.
public final class Letter {
private static int _letterValues[] = new int[]
{1, 2, 3, 4, 5, 8, 3, 5, 1, 1, 2, 3, 4, 5, 7, 8, 1, 2, 3, 4, 6, 6, 6, 6, 1, 7};

public static int lookUpLetterValue(char letter) {
return _letterValues[letter - 65];


package com.deepaksurti.numerology.calculate;

import java.util.Collection;
import java.util.Iterator;
import java.util.ArrayList;

* Created by IntelliJ IDEA.
* User: Deepak Surti
* Date: Dec 20, 2001
* Time: 8:37:32 PM
* To change this template use Options | File Templates.
public class NameManipulator {
public static Collection locateWordsInName(String name) {
Collection spaces = locateSpacesInName(name);
Iterator it = spaces.iterator();
Collection wordsInName = new ArrayList();
int beginIndex = 0, endIndex;
while(it.hasNext()) {
endIndex = ((Integer)it.next()).intValue();
wordsInName.add(name.substring(beginIndex, endIndex));
beginIndex = endIndex + 1;
wordsInName.add(name.substring(beginIndex, name.length()));
return wordsInName;

public static Collection locateSpacesInName(String name) {
name = name.toUpperCase();
char letter;
ArrayList spaces = new ArrayList();
for (int index = 0; index < letter =" name.charAt(index);">= 65 &&amp;amp;amp;amp;amp;amp;amp;amp; letter <=90) || (letter >= 48 && letter <= 57)){ continue; } else spaces.add(new Integer(index)); } return spaces; } } ---------------------------------------------------------------------------

The simple web interface looked like this :

Click to enlarge

Now I sit down with Ruby. And what I have. 1 tc_numerology.rb for test cases which is worth 93 lines but you know what it covers 68 assertions which is fantastic coverage. My complete test case is worth assertions.

And all my business aka domain logic is in just 1 numerology.rb file which is only 46 lines of code. So compare 46 to 283. Plus I was amazingly comfortable while writing ruby code. I felt like a child when I used to play with building blocks for hours and hours. Ruby is so much intutive.

And here comes the Ruby code: Compare this with java version above and you will see the difference for yourself:

module Numerology

Values = { "a" => "1", "b" => "2", "c" => "3", "d" => "4", "e" => "5", "f" => "8", "g" => "3",
"h" => "5", "i" => "1", "j" => "1", "k" => "2", "l" => "3", "m" => "4", "n" => "5",
"o" => "7", "p" => "8", "q" => "1", "r" => "2", "s" => "3", "t" => "4", "u" => "6",
"v" => "6", "w" => "6", "x" => "5", "y" => "1", "z" => "7"}

Power_numbers = [11,22,33,44,55,66,77,88,99]

class Calculator
def name_destiny_number(name)
names = name.split(/[^A-Za-z]/)
names.each {|name| name.downcase!.gsub!(/[a-z]/) {|ch| Numerology::Values[ch]}}
numbers = names.collect {|name| name.to_i}
numbers = numbers.collect {|num| num = Numerology::number(num)}
numbers.inject(0) {|x, sum| sum + x}

def name_material_number(name)

def date_destiny_number(date)
Numerology::number(date.day) + Numerology::number(date.month) + Numerology::number(date.year)

def date_material_number(date)


def Numerology.sum(x)
x / 10 > 0 ? (x % 10) + sum(x / 10) : x % 10

def Numerology.number(num)
while num > 9 and !Numerology::Power_numbers.include? num
num = sum(num)


And my ruby test case looks like this:

require 'test/unit'

$:.unshift File.join(File.dirname(__FILE__), "..", "lib")

require 'numerology'

require 'test/unit'

$:.unshift File.join(File.dirname(__FILE__), "..", "lib")

require 'numerology'

class TestNumerology < calculator =" Numerology::Calculator.new">

Now lets revisit the main code and see how it compares it with Janjay does::

class Calculator
def name_destiny_number(name)
names = name.split(/[^A-Za-z]/)
names.each {|name| name.downcase!.gsub!(/[a-z]/) {|ch| Numerology::Values[ch]}}
numbers = names.collect {|name| name.to_i}
numbers = numbers.collect {|num| num = Numerology::number(num)}
numbers.inject(0) {|x, sum| sum + x}

See first line splits a name into its individual words (what Janjay Sumani does)
Next it removes any additonal spaces user may have entered (Janjay doesnt care)
Next we replace each character with its value from hash map
next we just convert strings like "455812" to a number 455812 (Janjay does these 2 steps looking into his chart)
Next for each number like we saw in example right at the top we get reduced number. The line numbers = numbers.collect {|num| num = Numerology::number(num)} does the magic.
And then i find the sum using inject method on arrays.

See didnt it feel like Janjay was at work and not some stupid obsucre compiler that makes you a better break dancer than Michaeal Jackson? I bet...

The great ideas whcih differentiate Ruby viz blocks have been used here. When you wanna learn focus a lot on its library, built in classes, modules, how to package using gems , and more importantly blocks and closures. When I move to write Tk interface I can explain closures better. Blocks originated with iterators but thats not their only usage.

I cant explain Ruby here. I have just started but it has got me hooked. I now wnat to write 3 interfaces for this : one using Rails (thats coming next mth), one using Tk and one using AJax. And we will compare these 3, time it takes blah blah to java.
I am already putting my money on Ruby.

Nice pointer to start Ruby this. Have Andy and Dave's book 'Programming Ruby' by your side. If you are really keen to make a difference you will learn Ruby. Its a great journey.

And yes I will test this language out more thoroughly with EzExpense a home finance calculator which has some crazy logic, which finance app doesnt have. That will be FUN.

Oct 19, 2005

Thats what being called Humble

An extract from a news on Rediff Madhavan will host this new game show

"All I can say is, it has no relevance or connection to Kaun Banega Crorepati [the Indianised version of Who Wants To Become A Millionaire]. It's a different format. And we will not pitch it against KBC. Our show will be telecast on weekdays. Who on earth would dare to take on Mr [Amitabh] Bachchan?"

Now i like this..i think this show may be successful because they are intelligent enough to not take on AB. Well done Madhavan . You are way common sensical beyond those morons who did try to take on the giant AB and returned with miserable results..:-)