Monday, February 23, 2009

An Oscar for Globalization!

Slumdog millionaire swept the Oscars with 8 awards last night. I read a headline on CNN that said - "India erupts in a celebration for Slumdog". But was it an Indian movie? Was it a British movie? Which country did Slumdog belong to? I think the answer is none! As far as I know it was the first truly global movie to win so many oscars. The producers and directors of the movie were British, the story and setting was quintessential Indian and it was an American distributor who showed faith in it before the British distributors touched it. The American audience liked the movie much more before the world noticed it in a big way. In my opinion, globalization of the movies won at the Oscars last night.

Globalization perpetuates itself. Slumdog winning Oscars has an impact on the both sides. First of all rural India who knew A. R. Rehman very well but not necessarily know about the Oscars now knows about the Oscars. I am sure that more number of Indians saw this Oscars on the television than ever before. At the same time Indian musicians, cinema technicians and actors/actresses are getting global recognition. This will increase cooperation between Hollywood and Bollywood and spur projects of a similar nature - having the global setting. Globalization in the movie industry has truly come into light last night. The process of globalization of the movies is only going to accelerate here onwards.

I keep telling the critics of globalization in India who fear that western culture will destroy the Indian culture - Globalization is not one way. As you accept western influences and culture, the West will also be exposed to your culture. I keep telling people here too that what you see now is just the beginning - the beginning of the mixing of cultures, movies, people, languages.... It's in everybody's benefit to succumb to it and go with the flow.

Thursday, January 29, 2009

How to divide an amount into a large number of pieces

If somebody asked you to divide $10 among 3 people, how will you divide the money? 3.33, 3.33 and 3.33? The three amounts do not add back to $10. To accurately (but not necessary fairly) distribute $10 you will have to give $3.34 to one person. Thus when you add $3.33, $3.33 and $3.34 it adds up to $10.

How will you do this programatically in java? We faced this problem few months ago. It wasn't a trivial problem to solve. But Martin Fowler came to our rescue. His Money class does the magic. Let's look at it's divide method:

public Money[] divide(int denominator) {
BigInteger bigDenominator = BigInteger.valueOf(denominator);
Money[] result = new Money[denominator];
BigInteger simpleResult = amount.divide(bigDenominator);
for (int i = 0; i < denominator ; i++) {
result[i] = new Money(simpleResult, currency, true);
}
int remainder = amount.subtract(simpleResult.multiply(bigDenominator)).intValue();
for (int i=0; i < remainder; i++) {
result[i] = result[i].add(new Money(BigInteger.valueOf(1), currency, true));
}
return result;
}
The method above divides the given amount ($10) by a denominator - 3. All it's doing is dividing 10 / 3 and storing the result into an array - {3.33, 3.33, 3.33}. Then it finds out how many pennies are remaining by doing 10 - (3.33 * 3) = 0.01 - that is 1 penny. It starts distributing remaining pennies to the elements of the previously resulted array. As only one penny is remaining we just add this penny to the first element. Thus now we have {3.34, 3.33, 3.33}.

The algorithm ensures the if you add the distributed amount back, you will get the original amount back - 3.34 + 3.33 + 3.33 = 10. But the algorithm hogs memory if your denominator is a very big number. In our case, we had to divide an amount into 12 million pieces. It's very inefficient as it created array of 12 million elements! I changed the method in the following way to make the division memory efficient:


def divideEfficiently(int denominator) {
BigInteger bigDenominator = BigInteger.valueOf(denominator);
BigInteger simpleResult = amount.divide(bigDenominator);

def map = [:]
def dividedMoney = new Money(simpleResult)
for (int i = 0; i < denominator ; i++) {
map[dividedMoney] = map.get(dividedMoney, 0) + 1
}
int remainder = amount.subtract(simpleResult.multiply(bigDenominator)).intValue();
def Money one = new Money(BigInteger.valueOf(1))
def addedMoney = dividedMoney.add(one)
for (int i=0; i < remainder; i++) {
map[dividedMoney] = map.get(dividedMoney) - 1
map[addedMoney] = map.get(addedMoney, 0) + 1
}
return map;
}

The above method is similar but instead of giving an array of 3 elements, it gives a map of two elements [3.34 : 1, 3.33 : 2]. The map indicates that you have two shares of 3.33 and 1 share of 3.33. Your 12 million shares can be simply mentioned by two elements in a map!

Let me explain this with one more example. If you are trying to divide 11 in 13 pieces the original algorithm will give you following array : {0.85, 0.85, 0.85, .85, 0.85, 0.85, 0.85, .85, 0.84, 0.84, 0.84, .84, .84}. You can notice that there are only two unique elements in above array - .85 and .84. Thus the array can be expressed in the following map - [0.85 : 8, 0.84 : 5]. Even if your denominator is 12 million, you will always get two unique elements by Fowler's algorithm and hence the result can always be expressed as a map of two simple elements there by saving huge amount of memory.