Saturday, May 22, 2010

We aren't responsible

I was reading the paper and The Mumbai Mirror's headlines a few days ago went something like this "Criminal Negligence Leaves WR Commuter Critical". The article was with reference to a commuter who had been injured by a plank that fell on him because of negligence on part of the workers working at Churchgate station. This injury unfortunately has left him comatose and he is currently in a critical state in hospital. I wish him a speedy recovery.

Coming from a software centric world where EULAs and licenses accompany any piece of code that is shipped, it seems only natural that no one is really responsible for anything that they do and that any action on their behalf may have negative influences on others. Others need to watch out for anything that may hurt or otherwise injure them. It is the user's and only the user's sole responsibility to ensure his/her fitness and properiety and the user must account for anything that may go wrong during the course of using the product/software mentioned.

I have yet to see any license that says that they take sole responsibility for their product and that they could be held responsible for any damage arising due to negligence on their behalf. The closest I have come to it is Knuth's exponentially increasing reward for finding bugs in TeX. As far as free software is concerned, we shouldn't expect it. However in case we are paying for the software, shouldn't we demand it? I mean we are literally shelling out hard cash for that piece of code. We seem to have a right to want it to be bug-free...

Either ways, it seems no one wants to take responsibility for their code, so why not make it a de-facto standard. Instead, if someone out there is willing to say that they will take responsibility for screw ups (of any) then they should include it in the license agreement.

It starts off with software saying that it may not work well and ends up at coffee cups and hot dogs saying that their contents may be too hot for consumption.

What next? From what I see, there may now be notices on every pavement saying that people should walk on it on their own risk. Each lift will say that it could crash any minute and if it does; even due to any manufacturing defect or installation glitch, then company providing it should not be held responsible. Airplane and trains will warn travelers before they enter saying "Please account for the fact that you may not make it if you step in". Books may say "Read at your own peril. Your eyes may gouge out while reading this book, but don't blame us!!". When will all this end???

Saturday, May 15, 2010

Events: How to use them to your advantage

A very interesting conversation between a colleague and me resulted in some equally interesting learnings as far as I was concerned.

The topic of discussion was about whether certain functionality in a software should be implemented via events or via function calls directly to the concerned component. More concretely, should the coupling be via events as in a pubsub based system or should it be via known function end-points on specific objects.

If the event based approach is used, there is lose coupling, and the coupling is on events. Using the other approach, there is strong coupling and one component needs to know about the interfaces of the other component.

Let's take a toy example to analyze this situation.

Consider an interior stylist that is developing an integrated home theatre system. Say there are multiple components involved:
1. Speaker system
2. Television
3. CD player
4. Satellite system

For all practical purposes, users should not need to turn on each of the separate components separately (as they do today). They need not even know what the individual constituents of the system are. For that purpose, having a separate button that turns on the Television, one that turns on the speakers and one that controls the CD player seem overkill. Just the press of a single "start CD" button should do the needful.

Let's discuss various ways in which we can achieve the desired effect:
  1. Strongly couple all the components together so that starting the CD player also triggers the TV and the speaker system.

    What happens if the satellite system is turned on? It must also turn on the TV and speaker system. Tomorrow if there is a new device "USB photo viewer" that needs to use the display that the Television provides, it will also need to do the needful.

    This method seems to waste a lot of developer time and seems to be prone to errors. What if someone forgets to turn on the TV? Also each component needs to handle the case of when the TV/speaker is already on, etc...

    The CD player will work only with that TV set and speaker system that speaks a language that it understands (tied to an interface). Vendors will try to tie users to their interface in the hope of selling them all the components.

  2. Instead, if we just decouple all the system and couple them on events, things become much clearer and easier to work with.

    The "button.enterteinment.cdplayer", "button.enterteinment.satellite" and "button.enterteinment.usbdevice" events should be listened to by each of the components and they should react accordingly.

    Another thing to remember is how to name the events. We should NOT name events as "start.enterteinment.cdplayer". That sounds very imperative. Naming plays a very important role in how the rest of our system is built around these events. Wrongly named events can cause a lot of confusion and screw up the system even more than what you thought capable of doing!!! Event names should be suggestive of "something happening" and not of "something being asked for".

    Accordingly, events should not be named "do-this" and "do-that". Instead, prefer names like "this-happened" and "that-happened" so that listeners can react to these events in the way they deem most fit.

    By naming events imperatively, we immediately constrict their use cases to what we think they should be; defeating the original purposes of using events -- which is to free event raisers from thinking of what is to be done in reaction to a raised event.

Sunday, May 09, 2010

One line to teach you Object Oriented Programming (OOP)

"When modeling objects, model behaviour, not attributes"
Courtesy: Ramki

Probably the hottest summer I've seen in Mumbai

This is by far the hottest and stickiest summer I have seen in Mumbai since my stint on this planet.

Sunday, May 02, 2010

Protocol Buffers v/s HTTP

I was discussing serialization costs with my immediate superior, Ramki when one thing lead to another and I landed up wanting to compare the serialization and deserialization costs of protocol buffers (a binary format) to those of HTTP (a text based protocol) in python.

After performing some tests (in python), I observed that protobuf was taking almost 4 times the amount of time to deserialize data as compared to the simplistic HTTP based header parsing. Of course, these 2 are meant for different purposes and Ramki mentioned that a fixed format protocol would save data on the wire since the attribute names (header names in HTTP) need not be sent on the wire; just the values (header values in HTTP) are sufficient.

Also a binary protocol should be much faster as far as serialization and deserialization is concerned, but we found out that python's pack and unpack are a bit slow OR it is blazingly fast at doing string operations.

Here is a representative output from one such run of the program below:

ramki serialization time: 0.125000 seconds
ramki deserialization time: 0.156000 seconds
protobuf serialization time: 0.453000 seconds
protobuf deserialization time: 0.453000 seconds
http serialization time: 0.047000 seconds
http deserialization time: 0.125000 seconds

The code:

import sys
import message_pb2
import time
import struct

def multi_serialize(o, n):
fragments = []
for i in xrange(0, n):
data = o.SerializeToString()
fragments.append("%d\r\n" % len(data))
fragments.append(data)
return "".join(fragments)

def multi_parse(input, n):
il = len(input)
start = 0
objects = []
for i in xrange(0, n):
rnPos = input.find("\r\n", start)
if rnPos == -1:
print "Premature end of input. Terminating..."
return None
lenStr = input[start:rnPos]
start = rnPos + 2
lenInt = int(lenStr)
# Read off lenInt bytes off the stream
data = input[start:start + lenInt]
start += lenInt
obj = message_pb2.Header()
obj.ParseFromString(data)
objects.append(obj)
return objects


def http_header_create(request, headers):
line1 = "GET %s HTTP/1.1" % request
hLines = [line1]
for k,v in headers.items():
hLines.append(k + ": " + v)
return "\r\n".join(hLines) + "\r\n\r\n"

def http_header_parse(input):
parts = input.split("\r\n")
line1 = tuple(parts[0].split())
headers = { }
for i in xrange(1, len(parts)):
h = parts[i].split(": ")
if len(h) == 2:
k,v = h
headers[k] = v
return (line1, headers)

def http_multi_serialize(request, headers, n):
fragments = []
for i in xrange(0, n):
fragments.append(http_header_create(request, headers))
return "".join(fragments)

def http_multi_parse(input, n):
il = len(input)
start = 0
objects = []
for i in xrange(0, n):
delimPos = input.find("\r\n\r\n", start)
if delimPos == -1:
print "Premature end of input. Terminating..."
return None
headerString = input[start:delimPos]
headerObject = http_header_parse(headerString)
objects.append(headerObject)
start = delimPos + 4
return objects

def ramki_serialize(obj):
totalLength = 0
attrs = [ ]
for k,v in obj.__dict__.items():
totalLength += (2 + len(v))
attr = struct.pack("H", len(v)) + v
attrs.append(attr)
attrs.insert(0, struct.pack("H", totalLength))
return "".join(attrs)

class RamkiDummy(object):
pass

shortStruct = struct.Struct("H")

def ramki_deserialize(input):
# For now, we lose attribute names
d = RamkiDummy()
packetLength = shortStruct.unpack(input[0:2])[0]
s = 2
ctr = 0
while s < packetLength+2:
# print "CTR: " + str(ctr)
attrLength = shortStruct.unpack(input[s:s+2])[0]
s += 2
# Read attrLength bytes of data
attrValue = input[s:s+attrLength]
s += attrLength
setattr(d, "attr" + str(ctr), attrValue)
ctr += 1

return d

def ramki_multi_serialize(obj, n):
stream = []
for i in xrange(0, n):
stream.append(ramki_serialize(obj))
return "".join(stream)

def ramki_multi_deserialize(input, n):
objects = []
s = 0
for i in xrange(0, n):
objectLength = shortStruct.unpack(input[s:s+2])[0] + 2
obj = ramki_deserialize(input[s:s+objectLength])
s += objectLength
objects.append(obj)
return objects

def main():

class Dummy(object):
pass

d = Dummy()
d.request = "GET"
d.resource = "/user/ramki/getVcard/"
d.version = "1.1"
d.destination = "localhost:8080"
d.custom1 = "434552"
d.custom2 = "no"

s = time.time()
input = ramki_multi_serialize(d, 10000)
print "ramki serialization time: %f seconds" % (time.time() - s)

s = time.time()
ramki_multi_deserialize(input, 10000)
print "ramki deserialization time: %f seconds" % (time.time() - s)

h = message_pb2.Header()
h.request = "GET"
h.resource = "/user/ramki/getVcard/"
h.version = "1.1"
h.destination = "localhost:8080"
h.custom1 = "434552"
h.custom2 = "no"

s = time.time()
stream = multi_serialize(h, 10000)
print "protobuf serialization time: %f seconds" % (time.time() - s)

s = time.time()
objs = multi_parse(stream, 10000)
print "protobuf deserialization time: %f seconds" % (time.time() - s)

hh = { "Host": "localhost",
"X-MessageID": "33",
"X-ACKMessage": "100",
}

s = time.time()
stream = http_multi_serialize("/user/ramki/getVcard/", hh, 10000)
print "http serialization time: %f seconds" % (time.time() - s)

s = time.time()
objs = http_multi_parse(stream, 10000)
print "http deserialization time: %f seconds" % (time.time() - s)

return 0

sys.exit(main())


This page claims that protobuff deserialization time is 3478ns whereas I am seeing a time of 4530ns which is expected since we are running on different hardware.

From: here, it seems as it protobuf is good at packing ints but not strings.

In fact, none of the deserialization times even come close to the 1250ns that I see for http parsing. This is mainly because those methods do type conversion which HTTP is not doing.
If that is introduced into the mix, I guess those costs will add up too. However, the application that I want it for doesn't really need it, and there will be many applications that don't.

In the link above, many of the methods, serialization takes more time than deserialization which is slightly curious.

Thursday, April 22, 2010

Inheritance and extension

I have been stumped by this issue for a while, so I decided to write about it.

Say you have an element container called SimpleList which exposes the following methods(apart from others of course):
1. add(element): Adds 'element' to the SimpleList
2. addAll(elements): Adds 'elements' to the SimpleList

These methods are extensible(can be overriden and hence extended).

They are implemented as follows in SimpleList.

# Contract: Will add 'element' to SimpleList or throw an
# exception in case of an error.
method add(element)
# Adds element to the underlying data store/array

# Contract: Will add 'elements' to SimpleList or throw an
# exception in case of an error. This method may throw an
# exception after adding 'some' of the elements from 'elements'.
method addAll(elements)
for element in elements
this.add(element)


Fair enough till now.

Up comes someone who decides they can do better and they extend SimpleList and create ABetterSimpleList!!

They are implemented as follows in ABetterSimpleList.

# Contract: Will add 'element' to ABetterSimpleList or throw
# an exception in case of an error.
method add(element)
# Adds element to an underlying cache since SimpleList
# may take a while to add() this element.
if cache.size() > 20:
this.addAdd(cache)
cache.clear()

# Contract: Will add 'elements' to ABetterSimpleList or throw
# an exception in case of an error. This method may throw an
# exception after adding 'some' of the elements from 'elements'.
method addAll(elements)
# Just call the base class' addAll method


All contracts have been satisfied, but can you spot the subtle bug?

Yes, there is an infinite recursion here!! Calling add() on ABetterSimpleList will add elements to the cache till the cache grows to 20 elements in length. Once that happens, it will call addAll() which will call the base class' addAll() which will call (what it thinks is) it's add() function, except that it had been overridden by us to call addAll()!!

Well, how do you solve this?? I don't have a concrete answer myself, but just scratching the surface has lead me to believe that there are 2 type of class extensions:
1. Extending for the base class (I call this framework extension)
2. Extending for users/subclasses (I call this normal extension)

In case [1], it is expected that the base class will consume your interfaces so you program for the base class. However, in case [2], your consumers are externals and not internals like your base class. Hence, you should now program for them.

An important side effect of this is that classes that are meant to be consumed by subclasses (case [2]) should NOT use their own overridable methods in their own implementation or else they CAN NOT give any guarantees to their consumers (subclasses in this case). However, framework extended classes (case [1]) SHOULD use their own public interfaces since that IS the purpose of them allowing method overriding on those interfaces. They are expected to be the consumers of their subclass' funtionality.

Examples of each type of class:
1. Framework Extension: Java's Runnable, C++'s streambuf
2. Normal Extension: Java's LinkedList, AbstractList. Typically anything that is layered falls into this category

Patterns for Concurrent, Parallel, and Distributed Systems

I happened to chance up on this great site which describes Patterns for Concurrent, Parallel, and Distributed Systems.

I landed up here searching for the proactor and reactor patterns, both of which are described very well.

http://www.cs.wustl.edu/~schmidt/patterns-ace.html

Tuesday, February 02, 2010

An experiment with carbs

About a month ago, Appu, Abbas and myself met and Appu happened to mention that an increased intake of carbs. generally lent itself to hunger pangs if one did not eat for a while.
For the last month, I've been having only salad for lunch, and daal, vegetables and chapati(3 nos.) for dinner and have also been limiting my carb. intake by way of reducing the amount of sugar I add to my hot beverages.
However, yesterday I had 4 liquor chocolates (which Devdas had so generously brought back from New Zealand), 5 milk pedhas (courtesy Jaineev) and 2 Kaju Katris (courtesy Mukesh), which considerably increased my carb intake for that day. Furthermore, I had 5 chapatis and extra helpings of other stuff yesterday for dinner. I don't know if it had any direct link to the carb. intake, but I will be monitoring this more closely now.

Moments

I visited Sandeep in Bangalore when I had gone for the Agile 2010 conference in Jan 2010. Good times followed ;)

Monday, February 01, 2010

Vanilla Milk using natural vanilla extract

I started making vanilla extract in July 2009 using adaptations of the innumerable recipes available online. It's now been 7 months since I started so I decided to try out the extract for making vanilla milk (which btw I absolutely love and up to this point made using pulverized vanilla beans).
  • Attempt-1: Measure about 1 cup (approx. 200 ml) of milk in a glass, pour it in a vessel and heat. Add 1/2 tsp vanilla extract to the glass (which has traces of cool milk). The last bit caused the trace amounts of milk in the glass to curdle. However, pouring the heated milk and sugar in the glass did not curdle the rest of it. The whole drink smelt of alcohol though.

  • Attempt-2: This time, I decided to not leave trace amounts of milk before adding the extract to the glass. Again however, I did get some smell of alcohol.

  • Attempt-3: This time, I decided to do some research online and figure out if anyone else is facing the problem of an alcoholic smell in their extract. As it turns out, it is expected to be this way for a real extract!! (feature, not a bug ;) ). I also happened to read that adding sugar reduces the alcoholic smell, and that when this extract is used in cooking, most of the alcohol will in fact evaporate and hence not leave behind that alcoholic smell. So, this time, I added some sugar to the glass before adding the vanilla extract, and after pouring in the hot milk, I stirred for about 4-5 minutes before consuming the drink. Viola!! No smell now!!


Another nice link explaining a lot of things.

Friday, January 29, 2010

Eggless Brownies Recipe

Makes 1kg Eggless Brownies



Ingredients:






















































Flour (sifted):195g
Dark Chocolate:160g
Fat (Butter + Oil)120g (80g + 40g)
Water:255ml
Cocoa powder:2-3tsp
Sugar (castor or powder sugar):2 cups
Salt (if not using salter butter):1/2 tsp
Vanilla extract/essence:1 1/2 - 1 4/5 tsp
Baking powder:1 1/5 tsp(for guey brownies) - 1 1/2 tsp(for cakey/fluffy brownies)
Chopped walnuts:40g




Procedure:



  1. Grease and dust an 8" X 9" pan (basically 72 square inches in area), and pre-heat the oven to 180 degree celcius.


  2. Heat the water on a low flame till it is warm/mildly hot and add to it 1/3rd of the flour (65g). Do not remove the utensil from the flame, and continue stirring till the mixture thickens.


  3. Add the oil to the chocolate and melt the chocolate either in a microwave oven or on a double boiler.


  4. For making cakey(not guey) brownies, mix the sugar with the butter and whisk/beat till the mixture is light and fluffy. For making guey brownies, just mix the sugar with the flour and water mixture you just made.


  5. Mix the baking powder, cocoa powder and salt (if using unsalted butter) with the rest of the flour and sift it again a couple of times to mix them uniformly well.


  6. Add the vanilla extract with the flour and water mixture and mix it well.


  7. Now, mix all the portions that you have with each other and add the walnuts to this mixture. Make sure you mix it well. Perform this step quickly and briskly so that the baking powder doesn't wear out by the time you start baking it.


  8. Transfer the contents to the greaded and dusted pan, and bake in the oven for 45-55 minutes (or till you think it is done).


  9. Remove frm over and wait for it to cool a bit (about 30-45 minutes), cut into pieces and enjoy!!




Saturday, January 16, 2010

One week of salad

I started having salad last week for lunch every day, and it's going pretty well as of now. Bought supplies for the next week today.



Ingredients:

  • Iceberg lettuce

  • Lettuce

  • Purple/Green cabbage

  • Brocolli

  • Red/Green/Yellow Capsicum

  • Tomatoes

  • Cherry Tomatoes

  • Baby corn

  • Fresh Green Peas

  • Finely chopped carrots

  • Green/Black Olives

  • Soaked and sprouted moong and moth

  • Extra Virgin olive Oil (for the dressing)

  • Honey (for the dressing)

  • Salt (for the dressing, added just before eating)

  • Mixed Herbs (for the dressing)


Procedure:

  1. Cut and mix whatever you want to have in the salad. I generally choose about 6-8 items every day, and mix and match in any order I feel fit.

  2. Introduce the dressing (generally just olive oil and honey) except for the salt since the salt will make the vegetables dehydrate and lose their water. I take this tossed salad to office, so it is about 3hrs time from the time I mix it to the time that I consume it.


Saturday, January 09, 2010

It's funny to know....

.... that something you have thought of doing and have done has been thought of by someone else across the world and done in almost exactly the same way as you have....

It's saddening and encouraging at the same time. Saddening because it's not something novel any more. Someone has "been there.. and done that..". Encouraging because you know that you are not having any insanely weird and impractical thoughts and ideas and that you are solving some real problem out there.

This is the second time that this has happened to me, and it is a real confidence booster I should say!!

The project under question is StickyLinks. The exact same thing was done in 1997 and is called WebCite. The funny thing is that it was made for the exact same problem that I was trying to solve, which probably explains why it turned out to be so similar.

The thing that still gets to me is that even the layout of the version page (view where a version of a certain page is displayed) is almost identical. Both projects use frames. Both projects have a bookmarklet.

However, there are ways I plan to extend StickyLinks, so stay posted!!

ps. My next idea: To develop a search engine that will let you search for already existing ideas/concepts/implementations of thoughts that you may have and may think are novel. I use the internet (esp. the search engines) a lot to search for projects that I may want to undertake, just to check if it's already been done by someone else. Most of the time I have to search a lot of times, tweaking my search keywords ever so slightly in the hope of a match. Many a times, I fail to chance upon the right set of keywords (the words that the original author used to describe his/her idea/project) and am under the impression that the idea I have is novel/un-thought of. However, many times it does happen that such a thing does not exist. However, it is only time that lets you ascertain this (if a similar concept exists, you hear of it sooner rather than later, assuming you have shared it with friends).

Chocolate Rum Balls

This is been pending for a while now.
Barbara asked me how to make these last year!!!! (realistically, about a month ago) and I haven't yet gotten back to her. That is pretty bad of me.
Here goes nothing....



Ingredients:




























Chocolate sponge cake:about 250g
Dark chocolate:about 250g (preferably &ge 40% cocoa)
Fresh Cream:about 100g
Walnuts:about 100g (or to your taste)
Rum:to taste





Procedure:


  1. Crumble the cake well into.... well crumbles.... Use very soft hands to do this.

  2. Mix the rum with the crumbled cake, but don't form a paste.

  3. Melt the chocolate (always over steam).

  4. Heat the cream in a saucepan till it is simmering and mix it well with the melted chocolate.

  5. Make small pieces of the walnuts and add them to the chocolate and cream mixure and mix well again.

  6. Empty the cake crumbs into the mixture above and mix till it forms a solid paste which can be rolled into balls. Note: You may need more/less of the cake crumbs depending on how watery/viscous the chocolate and cream mixture is.

  7. Roll them into balls!!!! You can put a thin layer of melted butter or ghee (clarified butter) on your palms so that the stuff doesn't stick to your palms while mixing.





Merry Christmas, and have a Great New Year!! :) :)

Gaajar Halwa

I met Appu and Abbas today, and we had this nice talk about carbs. and how the lesser there are around and within us, the better it is for our kind of lifestyle. I have steadily reduced the amount of sugar I have with my cup of tea or ukada (or ukado since it is a gujarati recipe) and am okay with it.
The recipe below is in complete defiance of the statements above. However in my defense, I used much less sugar than I usually would have.



Ingredients:

































Grated fresh red carrots(gaajar):about 1kg
Cow's Milk (preferably full fat containing ≥ 9% SNF):about 2ltr
Sugar:to your taste, but you could start off with 200g
Cow's Ghee (clarified butter):2-3 Tbsp
Elaichi:seeds of 4-5 pods, well separated
Elaichi powder:1 tsp (or to taste)





Procedure:


  1. Take the Ghee in a saucepan and add the elaichi seeds, and heat the ghee till it is hot, and just till you hear a pop sound.



  2. Add the grated carrots and coat every bit of them with the Ghee (on a slow flame).




  3. Heat the milk in a saucepan till it is hot.




  4. Pour some (about 500ml) of the hot milk into the carrot and ghee mixture, turn up the flame to medium and stir continuously.



  5. The milk will come to a boil.



  6. We want to make mawa (or khoa) from the 1.5ltr of remaining milk. You can find out how this is done. Basically it involves simmering the milk till the water almost vaporizes. The semi-solid mass that is left will be used later in the making of our halwa.


  7. Once the mawa is made, mix it with the rest of the carrot mixture (which should have considerably thickened by now. I hope you were continuously stirring it all this while!!).


  8. Also add the sugar. The sugar will immediately melt and give off a lot of water. We need to burn off all this water.



  9. Stir continuously till the water evaporates and we are left with a semi-solid mass (more liquidy though).



  10. Evenly sprinkle the elaichi powder over this mass and stir continuously.



  11. Till the mixture thickens to a consistency of your choice.



  12. Let it cool, and enjoy!!!! :)



btw, this is the 100th post on this blog!!

Tuesday, November 24, 2009

An O(1) approach to the LFU page replacement algorithm

LFU: Least Frequently Used

The LFU algorithm evicts pages that have been least frequently used. If the cache is full, and one more page needs to be added, the page that has been used the least number of times is evicted from the cache.

How can we efficiently implement this algorithm? Each operation of the LRU algorithm can be implemented in worst case O(1) complexity. We can do the same for LFU as well.

For this, we maintain a doubly linked list where each node of the linked list looks like this:

struct CountNode
{
CountNode *prev, *next;
PageNode *root;
int count;
};

Each node of this linked list points to the root of another doubly linked list which holds the actual pages. All the pages in this 2nd linked list have the same usage count. The node for this linked list looks like this:

struct PageNode
{
PageNode *prev, *next;
CountNode *parent;
char pageData[4096];
};



The PageNode's parent member points to that CountNode of which it is a child. So there is a direct pointer from every PageNode to the corresponding CountNode it falls under. These extra links are not shown in the diagram to keep it simple.

The CountNode linked list's count member holds the usage count of each element under that node. So each PageNode under a CountNode having a count value of 6 will have been accessed 6 times.

How to implement the various operations?
  1. Insetion: To insert, we always add the new PageNode to the CountNode list with the count value of 1. This will always be the first node in the linked list pointed to by head. If the first CountNode pointed to by head is greater than 1, we just add a new CountNode with a count value of 1 and then perform the insertion. All this can be done in time O(1).

  2. Deletion: We will delete nodes, only if the cache is full, and this deletion will always happen from the CountNode list which has the least count. So, we just follow head, and delete a PageNode in such a CountNode. Additionally, if that CountNode happens to become empty because of this deletion, we also delete that CountNode. This too takes time O(1).

  3. Access: Access involves incrementing the count of a PageNode, i.e. moving the accessed PageNode from it's CountNode list to a CountNode list with a count value that is 1 greater than it's current count value. We maintain pointers to the CountNode in the PageNode. This makes deleting the PageNode(and possibly the CountNode to which it belonged) a constant time operation. After that is done, we can insert a new CountNode that has a count value of 1 more than the CountNode from which the accessed PageNode was removed. If such a CountNode does not exist, we can always create it first. All this can also be done in constant time, making the whole process O(1).

    A lot of people have asked me how they can get to a PageNode in the first place. The answer to that question is that we maintain a hash table which hashes an object(page address, integer, etc...) such that accessing it (getting to the PageNode that that object corresponds to) can be accomplished in O(1) time.


This implementation takes advantage of the fact that:
  1. When we add a new object to the cache, it is always going to start off with a use count of 1, and

  2. Whenever we access an object, it's use count will go up by exactly 1.


I haven't found any resource that says that LFU can be implemented in time O(1). If you (reader) find any, please do let me know.

Saturday, November 21, 2009

The Missionaries and Cannibals Problem

Some reading before you start: http://en.wikipedia.org/wiki/Missionaries_and_cannibals_problem

Problem Statement:
[From the link above] "In the missionaries and cannibals problem, three missionaries and three cannibals must cross a river using a boat which can carry at most two people, under the constraint that, for both banks, if there are missionaries present on the bank, they cannot be outnumbered by cannibals (if they were, the cannibals would eat the missionaries.) The boat cannot cross the river by itself with no people on board."

Solution:
We will solve the generalized version of this problem, wherein there are C cannibals and M missionaries, and at most P people are allowed on the boat simultaneously.

This problem can be solved by noticing that at every stage, we can encode the state of the problem by using 3 variables, (nc, nm, shore). nc is the number of cannibals, nm is the number of missionaries and shore is either 0 or 1, which signifies whether nc and nm represent the count on the source or the destination shore respectively.

Thus, there are at most 2 x n2 states that the problem can be at any point in time.

We can use BFS (breadth first search) to perform an exhaustive search on the search space to find a solution if one exists. The run-time complexity of doing so is O(CM P2). Below is the Python2.5 code that solves this problem using the BFS search method.



import sys
import string
from collections import deque


states = [[], []]
dq = deque()
nc = 0
nm = 0
c = 0
combinations = [ ]


def gen_combinations():
global c, combinations

for i in xrange(0,c+1):
for j in xrange(0,c+1):
if i+j>0 and i+j<=c:
combinations.append((i,j))


def init_states():
global nc, nm, states
for i in xrange(0, nc+1):
states[0].append([])
states[1].append([])
for j in xrange(0, nm+1):
states[0][i].append(-1)
states[1][i].append(-1)


def is_valid_state(nc, nm):
return (nm>=nc) or (nm==0) or (nc==0)


def bfs():
global dq, states, nc, mn, c, combinations

while (len(dq) > 0) and states[1][nc][nm] == -1:
(x,y,depth,boat) = dq.popleft()

present = boat
next = 1-boat

if states[present][x][y] != -1:
continue

states[present][x][y] = depth

for comb in combinations:
(dx,dy) = comb

if x>=dx and y>=dy:
new_st = (nc-(x-dx),nm-(y-dy),depth+1,next)
(lx,ly) = (nc-(x-dx),nm-(y-dy))
(rx,ry) = (nc-lx,nm-ly)

if is_valid_state(lx, ly) and is_valid_state(rx, ry) \
and states[next][lx][ly] == -1:
dq.append(new_st)



def main():
global dq, nc, nm, c, combinations, states
input = string.split(raw_input())
nc = int(input[0])
nm = int(input[1])
c = int(input[2])

init_states()
gen_combinations()

dq.append((nc, nm, 0, 0))
bfs()

print states[1][nc][nm]

return 0


if __name__ == "__main__":
sys.exit(main())

Friday, November 20, 2009

The Capacity C Torch Problem

I stumbled upon the Capacity C Torch problem, and found it really interesting.
I'll start off with a few resources:
  1. http://aps.cs.nott.ac.uk/2008/05/06/the-capacity-c-torch-problem-2/

  2. http://www.tutor.ms.unimelb.edu.au/bridge/

  3. http://en.wikipedia.org/wiki/Bridge_and_torch_problem

  4. http://www.springerlink.com/content/935641175550x527/


Problem Definition:
There is a group (G) of people that wishes to cross a bridge in the dark. Each person takes a certain amount of time to cross the bridge. There is only 1 torch available. The bridge can hold at most C people at any one time. Every time a group of people cross the bridge, they need to carry the torch with them. One torch is sufficient to light the path for at most C people at a time. When multiple people cross at the same time, the entire group moves at the speed of the slowest person in the group. Given the values for G, C and the time that each person takes to cross, find the least amount of time that would be required to get the whole group across to the other side.

Expected Complexity of the solution: This solution can be solved using a computer program having a run-time complexity of O(n2), where n is the number of people in the group G [ |G| = n ].

Solution:
Step-1: Let us first concentrate only on how we will divide up the people into sets and in what order we will take them across(from size A to side B). We shall re-visit the problem of which person to get back to bring the torch back from side B to side A.

Let us take some values for the variables G and C.

Example-1: Let |G|=15 and C=5

In this case, we can easily divide people into 3 sets of size 5 each.

We'll sort all the people according to the time they take and group them starting from the slowest person. It can be seen that it is beneficial to club all the slow people together. So, we group the 15th, 14th, 13th, 12th and 11th person in one group, and so on..

We'll take the 1st group(the one with the 5 fastest people) and move them across first. Since someone needs to come back with the torch, it had rather be the quickest person, so we make sure he is across so that he can return.

We then take the 2nd group followed by the 3rd.

Example-2: Let |G|=16 and C=5

In this case, we are left with 1 person after dividing into sets of 5 each. No matter what we do, we will have 4 sets to deal with. We also note that it makes no sense to move just 1 person across. So, the way we make sets is {2,4,5,5}.
Why not divide as {3,3,4,4}? Well, if we do it like the latter case, then the 1st group will have the time of the 3rd person, and not the 2nd like in the former case. In both case, everything else remains the same, except if the 3rd person is slower than the 2nd one, we will have increased the total time required to cross. This is why we optimally divide in the former way.

Example-3: Let |G|=17 and C=5

Again, in this case, we optimally divide as {2,5,5,5}. We note that no other division is possible.

Example-4: Let |G|=18 and C=5

Again, in this case, we optimally divide as {3,5,5,5}. We note that no other division is possible.

Example-5: Let |G|=19 and C=5

Again, in this case, we optimally divide as {4,5,5,5}. We note that no other division is possible.


Step-2: Now, we shall concentrate on the problem of which people should bring the torch back from side B to side A, so that the next group on side A can cross the bridge to side B. Let us call these people torch bearers. The same problem also asks and how many at a time to bring back (i.e. How many torch bearers should move from side B to side A without returning) when sets of people are being transferred from side A to side B.

[This is where you should try figuring out for yourself whether you will send 1, 2, 3, 4, 5 (or more) groups at a time (without the torch bearers returning to side B)]

For example, suppose we have a group of people, [1,1,1,1,1,1,4,5,6,7] and C=3.
It is easy to see that once we have 2 people across, we can always get more across without having the torch bearers coming back to side B.

If we decide to work such that every time 2 torch bearers cross over to side A, they return to side B, we get the following scenario: The mean cost of transferring a set from side A to side B, and back would be 1(1st torch bearer from B to A) + 1(2nd torch bearer from B to A) + 1(1 and 2 back from side A to side B) = 3/1 (since we were able to get only 1 set across).

If we decide to work such that every time 3 torch bearers cross over to side A, they return to side B, we get the following scenario: The mean cost of transferring a set from side A to side B, and back would be 1 + 1 + 1 + 1(1, 2 and 3 back from side A to side B) = 4/2 (since we were able to get 2 sets across).

Similarly, if we decide to work such that every time 5 torch bearers cross over to side A, they return to side B, we get the following scenario. The mean cost of transferring a set from side A to side B would be 5+1(1, 2 and 3 back from side A to side B)+1(1 from side B to side A)+1(1, 4 and 5 back from side A to side B) = 8/4 (since we were able to get 4 sets across).

We observe that the mean cost went down if we took more torch bearers at a time. However, it is also easy to see that this is not always true. It depends entirely on the time that each torch bearer takes to cross the bridge.

We could also have a case where we have more than 3 torch bearers crossing from B to A, without coming back (like we sent 5 torch bearers at once in the example above).

We can NOT make a greedy choice as to how many sets to take across. i.e. How many torch bearers to send from B to A without them returning. This is where dynamic programming comes to the rescue.

Suppose |G|=47 and C=5
We will optimally divide into sets {2,5,5,5,5,5,5,5,5,5}.

The best way to take all 10 sets across is the best of:
  1. The best way to take all across without any torch bearer coming back unless all initial groups are across

  2. The best way to take the first 9 groups plus the best way to take the last group

  3. The best way to take the first 8 groups plus the best way to take the last 2 groups

  4. ...

  5. The best way to take the first group plus the best way to take the last 9 groups

The cost for computing these values using dynamic programming or memoization is O(n2). We can use these techniques because there are many overlapping sub-problems, and the other requirements for dynamic programming match.

We can pre-compute the cost required to take 1, 2, 3, 4, etc... groups at a time and store it in a lookup table. The time required to do this is O(n2).

Thus, we can solve the whole problem in time O(n2).

Sunday, October 25, 2009

Wordlist for GRE

Hello people, I have made a simplistic wordlist tool for GRE preparation. I've been asked by a well-wisher to post it here, so here it is: http://wordlist.dhruvbird.com/.

Saturday, October 17, 2009

Masala Matrix


Just a ready reckoner for me to look up to figure out how vegetables and lentils are made at my home.



Recipe Fat Rai (mustard seeds) Jeera Methi seeds Hing (asafoetida) Green chilli (whole) Kadi patta Haldi Salt Ginger paste Dhania and jeera powder to season
Dudhi (bottle gourd) Ghee No Yes No Yes No Yes No Yes Yes No
Tendli Ghee/Oil Yes No No Yes Yes No Yes Yes No Yes
Karela (bitter gourd)[1] Ghee Yes No No Yes Yes No Yes Yes Yes Yes
Dudhi + Dal (chana or tur daal)[2] Ghee Yes Yes Yes Yes Yes Yes Yes Yes Yes No
Cauliflower (fool gobi) Oil Yes No No Yes Yes No Yes Yes No Yes
Cabbage (patta gobi)[3] Oil Yes No No Yes Yes No Yes Yes No Yes
Tur Daal[4] Ghee Yes Yes Yes Yes Yes Yes Yes Yes Yes No
Aaloo mutter and tomato sabzi[5] Ghee No Yes No Yes Yes Yes Yes Yes No Yes
Pumpkin (bhopda) sabzi Ghee/Oil No No Yes Yes Maybe No No Yes No Yes
Fanshi (french beans) sabzi Ghee/Oil Yes No No Yes Yes No Yes[6] Yes Yes Yes
Moong daal (yellow) Ghee/Oil Yes Yes No Yes Yes Yes Yes Yes Yes No



[1]: Also put jaggery(gud), kaju(cashew) and kishmish(sultanas).
[2]: Also put jaggery(gud), kokam and corriander leaves to season.
[3]: You may optionally add tomatoes halfway through cooking the cabbage, and also add jaggery(gud) if you add tomatoes.
[4]: You can also add jaggery(gud) and kokam. It gives a very good taste to the daal. If you don't want to add gud and kokam, you can add lasun(garlic) to give it a nice taste and aroma. A 3rd option is to add tomatoes. If adding tomatoes, leave out the kokam, but you should add jaggery and may optionally add garlic.
[5]: You can also put a bit of jaggery(gud) into this preparation.
[6]: Add Haldi only if you are adding potatoes to the sabzi.
* Dhania powder is generally added only to vegetable preparations and not to daal preparations.

Thursday, October 08, 2009

Online hindi dictionary

I've been trying to find an online hindi dictionary where I can enter the text in english, and the system transcribes it and searches for the meaning. However, the best results I have got are by using google's transliteration tool(http://www.google.com/transliterate/indic) followed by a google search for the resulting word.
That apart, this site: http://www.websters-dictionary-online.org/ seems to have a lot of words. Make sure you choose the "non-english" option when you search.

Sunday, July 26, 2009

Lip-smacking Rasgulla recipe

I have tried for long to make rasgullas that taste like the ones I had a Ganguram's in Kolkata. I tried buying rasgullas from many shops, and tried making on my own in the hope of being able to reproduce that taste and texture that had lulled me into have a lot many Rasgullas that rainy day in Kolkata, but to no avail. None came even a close second.... Then, I read somewhere the milk that is curdled should be curdled slowly, taking care not to shock it, so I decided to try it out.... The rest is history....

The secret of making good, no GREAT tasting rasgullas is in what milk you use and how you go about curdling it and then processing it. Every step is very important, but I wasn't able to get the 2nd one right for quite a while. I finally tasted success (and moth-watering rasgullas) after a long time yesterday. I'll mention how you can go about reproducing them at home....

  1. Buy cow's milk for making rasgullas. 3.5% to 6.0% fat content is alright. Do not get low fat milk

  2. Boil it till about 10% of it boils off, taking care to not let it stick to the vessel. To ensure that, keep stirring as you boil it

  3. For 1 litre of milk, you will need about 2-3 tsp of vinegar or about 3/4th of a lime's juice. IMPORTANT: Dilute this juice in about 1 cup(240ml) of water

  4. Now, slowly keep adding this juice to the boiling milk, making sure to stir all the time. You can add about 1/4th every time, and stir for a minute. Do this about 4 times, and keep stirring and heating the milk on a low-medium flame. The milk should continuously keep curdling

  5. The milk is completely curdled when it separates into while solid and a greenish liquid

  6. Make sure that you do this curdling VERY VERY slowly, otherwise the paneer will result in rubbery rasgullas

  7. Now, separate the solid part(paneer) using a muslin cloth and squeeze out as much water as your possibly can. You can wash the paneer to remove the acidic part and squeeze out again, as much water content as you can

  8. Let this paneer dry up for about 30-45mins

  9. Now, you can follow any standard rasgulla recipe that tells you to knead the dough, form balls and cook them in boiling sugar syrup. However, I would like to clarify a few things

  10. The ratio of sugar:water in the boiling syrup should be 1:6 or lesser. I have heard some people boil the paneer balls in just water

  11. Make sure you roll the paneer balls tight and their surface is smooth. You can smear a bit of ghee(clarified butter) on your hands while rolling to ensure that they don't stick to your palm, and result in smooth balls



Use these rasgullas as rasgullas by dipping them in 1:2(sugar:water) syrup or by squeezing out the water(on cooling) and dipping them in rabri(to make yummy rasmalai!!!!)

Some lessons learnt

I have been working closely with this person called "Ramki", and have learnt a lot of interesting things from him that I wish to share. I don't know if I'll keep appending them to this post or create a new one each time. I guess it depends on my mood and the context and other such stuff....

  1. Never use filenames or variable names in an application that have the name of the product in it. If you ever decide to change the name of the application, you'll have to change all those file and variable names too. This can be a nightmare.

  2. When creating database tables which hold the email address of the user, also use a unique user ID. This allows users to change their email IDs when they please. If you use the email ID as the primary key(like how I was going to), it would not allow a change of email address in a cheap fashion. You would probably have to do an ON UPDATE CASCADE, etc.... and it would be quite an expensive operation.

Sunday, July 19, 2009

Sita Sings The Blues

I have to start off by saying that "Sita Sings The Blues" has to be one of the most influential movie I have ever seen. In the sense that it has prompted me to notice and think about a lot of things, and I think especially since I am from India.

There are many aspects of the movie I really like and I'll try talking about each one in as much detail as I feel necessary.

  • Lots of things have been left to the imagination of the audience even though a lot many have been explained by way of the random conversations that happen between the 3 narrators in the movie. I think it was very natural to make them say the things that they did, and the way that they casually argue with each other. Also, the conversations weren't casual enough to call them loose.

  • The music given is quite apt and makes you want to listen to it more often. The title track "Sita in Space" is trance-like in nature and makes use of instruments that sound Indian as well. I felt that the way Lord Rama is first shown being waited upon by Sita and the last scene which has the same scene with the roles reversed is quite an outstanding and representative of a lot of things.

  • The way that all the characters and their relationships to each other are shown upfront is something really neat. There have been times when I've seen movies and only towards the end have I fully understood how each of the characters are related to each other(when the story depended upon the viewer knowing these relationships up front).

  • I found the scene is which Kaikayee is shown to be a nurse taking care of Raja Dashrath quite hilarious.

  • There is another scene in which Nina is shown almost completely undressed, sleeping by her husband's side and her husband wants nothing to do with her when we hear a dog barking in the background. This was a scene that I was most impressed by because it felt so real, since that is exactly what I hear at many places(a dog barking in the night time). The level of attention to detail at places in the movie is really commendable!





This is a post in progress, and I shall keep updating it regularly.... Till then, you can watch the movie for free here. The song "Sita In Space" is really nice....

Saturday, July 18, 2009

Garlic and Herb Chapati

As always, I'm a bit lazy and don't want to spend time baking bread(it is a very long and drawn out process). However I felt like having focaccia(yes the yummy bread with herbs, garlic and loooots of olive oil), so I decided to make a similarly flavoured chapati and see how it turns out.




Ingredients:












































Whole Wheat Flour:2 cups + more for dusting
Water:Enough to make a really hard dough(we'll soften it up using lots of Olive Oil!!)
Softened Salted Butter:5 Tbsp
The Best Extra Virgin Olive Oil that you can get your hands on and afford:5 Tbsp
Mixed Dried Herbs(Parsley, Basil, Oregano, Rosemary, Thyme):1-2 Tbsp
Salt:1/4 tsp or to taste
Fresh Garlic Paste(it needs to be FRESH!!):of about 10 cloves
An appetite:as much as you can squeeze in!!






Procedure:


  1. Make a very hard dough from the whole wheat flour, water, herbs and garlic paste(take a really deep sniff, close your eyes, and savour the smell for a while).


  2. Use all the Olive Oil and mix it with the dough to make it hard(very hard to hard).


  3. Use this dough to make about 8-10 portions for rolling out.


  4. Keep tava(pan) for heating up on a slow flame. This will ensure that your tava is heated up evenly and your chapati won't get burnt or cooked unevenly.


  5. Roll out the chapati apply dusting flour regularly to prevent it from sticking. Roll out slightly thicker than standard chapatis because we have garlic and herbs in the dough. They may cause the chapati to puncture if we roll it out too thin. If the chapati gets punctured, then it won't balloon like we want it to.


  6. Cook the first size on a slow flame on the tava just until small boils begin to appear on the top surface.


  7. Turn the chapati over and cook on medium flame, turning the chapati so that the sides are cooked well. Always keep the sides in the center of the flame. The center of the chapati will get cooked well automatically. Now, larger boils will appear on the surface, and the under-surface will have brown spots on it.


  8. Make the flame high, remove the chapati from the tava quickly, remove the tava from the stove and turn the chapati up-side-down on the direct flame. Watch it balloon!!!! (if you've done everything well till now. It took me a month and lots of flat chapatis to get to this stage).


  9. Turn it around for just 1 second(or for symmetry as Appu would put it).


  10. Take it off the flame and apply a little of the melted butter while it is still steaming hot.... Smell it again and again till you think you've attained nirvana....


  11. Eat it!!!!



Friday, July 17, 2009

YAVFS

Yet Another Versioning File System....

I've been reading about Versioning and Snapshoting File Systems and here is a mini-dump of what I think so far. Please correct me if I'm mistaken....

I saw a few file systems with slightly more than a cursory glance, and here are my comments:

  1. ext3cow: This is very close to what I have in mind for a versioning and continuous snapshoting file system. However, it does not agree with some of my "requirements of a versioning and continuous snapshoting file system"(below).

  2. Elephant File System: This is probably one of the earlier snapshoting/versioning file systems and has been implemented on BSD. It is modeled on BSD's FFS. It does a great job of doing what it says it does. I like everything about it except that I can't use it on Linux.

  3. NetApp's WAFL: This again is mainly solving a different problem, that of providing very fast and safe storage on a storage appliance. To the best of my knowledge, you need to trigger a snapshot(though the process itself does not take more than a few seconds), and the number of snapshots are restricted to a fixed number(32 or 256). This may be done using hourly cron jobs, etc.... The interface of getting previous versions of files is a little clumsy though.


Requirements of a Versioning and Continuous Snapshoting file system:

  1. It should be able to store a large number of versions of files and directories alike

  2. It should be able to do so very fast and without any user intervention. ie. Snapshoting should not be user-triggered, but should be done automatically on every close()

  3. You should not need to re-compile the kernel to get this functionality

  4. You should be able to apply this to a specific directory root. This means that you should be able to snapshot parts of your directory tree. You should not incur a performance penalty for accessing file out of this region of interest

  5. You should have policies for controlling which file to snapshot and version files based on file attributes such as size, name, MIME type, etc....

  6. The interface for accessing continuous-in-time file versions should be very clean and fairly intuitive, and it should be fairly easy to write tools around it so that GUI/web-based access can be enabled

  7. You should be able to enable this functionality on any file system(and not require to re-format the partition on which you wish to enable it)

  8. You should be able to disable this operation at any point in time and get back to accessing the most recent versions of the versioned files using the earlier access methods without any performance penalty. ie. Users should be able to turn on and off this functionality at will and it should allow users to proof this on real workloads without them having to make any drastic changes in their environments

  9. The operations performed should be safe, and should not result in data corruption

  10. The system should be easy to install and set up



I have in mind something that satisfies the requirements mentioned above....

Tuesday, July 14, 2009

NextGen Storage??

I've been thinking about what storage systems have in store for us in the future. I mean I've been trying to follow the progress of these beasts, and the next big thing I think should be storage devices that have in-built support for some form of transactional memory. Lots of file-system drivers are building consistency mechanisms into their implementation by using logging in some form or the other. This logging is happening on the same medium as the one where data is being stored. A consistent view of the data is formed by looking at (data+log) as a unit of storage.

I think that logging implementations would benefit a great deal if they had some sort of hardware support. For example, NetApp's WAFL is utilizing Flash memory to store it's writes. This I think is a nice way to look at the problem at hand, and if device manufacturers could integrate some of this on to their device using some nice interface, I think that file-systems of the future could be much faster than they presently are.

The only problem that I do however see with this approach is that the flash memory may wear out and cease to function much faster than the magnetic stable storage. A log-based file-system(or storage structure) would be needed to store the writes on the flash storage(something like JFFS maybe).

Crispy Butter Chapati.... yummm....

I have stopped making bread these days because I prefer eating chapatis. They not only take lesser time, but also involve eating a lot lesser flour. Besides, they are thin, can be made crispy easily, and I've been used to eating them for a while. So, I've decided to experiment with different types of chapatis(whole wheat Indian flat-bread). I don't have any pics. of chapatis I've made, but I'm sure google's image search will show up a faithful representation. Or you can visit this wikipedia page about chapatis.

My latest favourite is a layered chapati with layers of butter in between. Yesterday, it was raining quire heavily so our maid decided to spend the night at our place. I was observing her make her chapatis and she made this chapati with oil and flour in the middle, folded it and started rolling again. She was basically layering her chapatis. That's when I remembered that my mother used to feed me something similar as a kid. However, these tasted like run of the mill chapatis, so I decided to innovate and use butter as the separating medium. Believe you me, this adds amazing flavour and taste to the chapati, and it tastes so good that you can eat it as-is!!




Ingredients:



















Whole Wheat Flour:2 cups + more for dusting
Water:Enough to make a hard dough
Softened Salted Butter:15 Tbsp






Procedure:


  1. Make a hard dough from the whole wheat flour and water.


  2. Use about 1 Tbsp of Butter and mix it with the dough.


  3. Use this dough to make about 8 portions for rolling out.


  4. Keep tava(pan) for heating up on a slow flame. This will ensure that your tava is heated up evenly and your chapati won't get burnt or cooked unevenly.


  5. Roll out cup size and apply butter generously. Apply dusting flour on the buttered side and fold in half.


  6. Repeat the above step one more time to get 2 folds.


  7. Now roll out completely(using dusting whenever necessary) into a chapati.


  8. Cook the first size on a slow flame on the tava just until small boils begin to appear on the top surface.


  9. Turn the chapati over and apply butter on the complete surface generously. Cook well.


  10. Turn it around again, and apply butter on this side now. Cook well.


  11. The more you change sides of the chapati, the more crispy it's surface will get.


  12. Cook till done, and you have achieved the level of crispness that you want.


  13. Eat it!!!!



Saturday, July 04, 2009

Awesome day!!!!

Thanks Anshuman, Anirban, Anushray, Amit and Anup for being there and making it so much fun for me!!!!

Sunday, June 28, 2009

Kerala: A short story

A short account of the excellent trip we(Sandesh, Pascal, Barbara and I) had to Kerala(God's own country).

20th June, 2009: Left from Mumbai, Lokmanya Tilak Terminus at 11:40am by Netravati Express. The train journey was essentially uneventful with us eating stuff we had brought from home. We avoided the train food as much as possible since it is known to down your spirits.

21st June, 2009: Anyhow, we couldn't avoid calling for breakfast when an undercooked dossa greeted our bile-infested stomachs and was probably digested. We got off at 2:50pm(the scheduled arrival time for the train.. surprise! surprise! the train was on time!!) at Ernakulam Junction. We did run into some (very little) trouble locating our driver for the trip(Pradeesh), but we eventually did find him. He took us to the first place we were supposed to go to: Kapithan Inn at Kochi. This is a nice home-stay run by a very friendly lady named Pushpa. The time spent there was really nice. We visited the beach, which has fisher-folk that use Chinese Fishing Nets to catch their prey. Kathakali dance performances take place every evening at 7pm. After a nice stroll, we decided to get something to eat. Finding a good eatery wasn't easy, but we did manage to find one called "Elite Inn". The waiter there was really over-worked but was good.... The food was good, and we ate well.

22nd June, 2009: Breakfast was at Elite Inn, and we and headed off to Kumarakom for the House-boat stay in the back waters. This was really the bestest of times we had.... There were 3 people waiting on us, The Chef(Anish), the driver(Meneesh) and the third took over when the driver was tired. Frankly speaking there was nothing to get tired about, but what the heck!! And I guess these guys must be finding it slightly monotonous to do the same thing every time, and greet everyone with the same enthusiasm and show them around.... This however, was a truly amazing experience.... Neither words nor pictures would do justice to what we experienced on the house boat. The back waters are a very still mass of water where the house boat just slithered along beautifully. We had fresh sunari(golden) coconuts and good food all around.

23rd June, 2009: Again, amazing breakfast and a very serene ride back to where we started off. This ended at about 10:00am. From here, we took the car and headed off to Thekkady. This was a slightly tiring and longish drive(about 41/2 hrs). We had stopped at a small place to have some tea. These long drives on hills really get to me cause there are so many sharp turns and when you are turning on these roads, all the food in your stomach starts to move about, and you feel giddy and sleepy. Well, we reached our place of stay -- Cardamom Club. This is another heaven on earth. There are about 4 small cottages on a small hillock over looking a treehouse. Behind the cottages is a hill on which Cardamom Club's plantations reside. The porch(the hillock on which the cottages are) is also filled with cardamon, vanilla and pepper plants. There are also jackfruit, papaya and mango trees here. The staff(Lijo and Shibu) was really co-operative and the food was really awesome! We had mango juice and papaya from fruits that grew in their own plantations. There is a old lady that did the cooking. She had the most amazing smile.... It reminded me of happiness.... :)

24th June, 2009: Went to a spice garden(Deepa Spices). Didn't like it so much. We would recommend other places like Abraham's Spice Garden, which is recommended by Lonely Planet. The one that we went to didn't show us much and the spices there were very highly priced. At 3:30pm we left for a boat ride in the Periyar Wildlife Reserve. We made it _just_ in time for the 4:00pm boat. However, Shibu had already bought tickets for us(you get them an hour before the boat ride) which is why we were able to go. The boat ride was nice.... It reminded Sandesh of scenes from Jurassic park. We didn't see to many wild animals though. We saw cows, bull, deer, pigs and some birds(the name of whom I do not know). The place closes at 6:00pm(which is also when the boat ride ends). We bought some spices after moving about in many shops and retired for the night after dinner.

25th June, 2009: Left for Munnar. Stopped on the way at a Spice Garden that was a home-run place. Really liked this place. Just bought stuff from here. They have the plantation, their home and the factory in one place. They grow their own vegetables to eat as well!! Again, longish drive that I didn't like too much. However, Pascal stopped us on the way and we took a nice 2 hour break at the Kannan Devan tea gardens. We spotted some cow munching grass and not doing much ;-) On reaching Munnar(about 4:30pm) we had lunch at some restaurant. I don't remember the name, but it was alright. We reached the home stay(Aranyaka) at about 5:30pm. It was too late to move out after that because of the mist so we retired for the day. The person who owned and was managing the home stay was a lady named Poornima. The person who was entertaining us was named Suresh.

26th June, 2009: We has good breakfast(tea, toast and omlette) and left at about 9:40am for Mattupatty dam. We thought there would be pedal boating out there, but there was only speed boating there. We were told that this time last year, the water on the dam was 120ft, but this time it was just 60ft, so there had been lesser rainfall this year as compared to last year. We were told that pedal boating would be available at the dam about 10km ahead. This dam is called Kundala Dam. We reached there to find out that we had not been lied to and in fact had pedal boats!! So, we hired them for 30min each(up to 3 ppl. in each pedal boat, but since there were 4 of us, we too 2 each). This was a really nice experience!! There were ducks in the lake too. Halfway, we decided to stay on for 30 min more. We were able to cover the whole lake :) After that, we went to echo point. There was nothing much interesting happening here[interesting incident with Barbara...]. Then we went back to have lunch. We hunted for some nice place and finally settled on Hotel Saravan Bhavan which we thought would be good. And it turned out to be an excellent place to have authentic South-Indian food. We would recommend it to everyone who visits Munnar.

27th June, 2009: We had to start off early(about 8:30am) for Ernakulam Junction since we had a train to catch at 2:15pm. The trip to the station was said to take about 4hrs 30min. We bought halwa, chips and bananas on the way and reached the station just in time(about 15mins to spare).

28th June, 2009: I didn't have any breakfast in the train, but had lunch. They had nice big kerala rice along with sambhar. I was really hungry at that time. When I reached home, I had khari puris, shrikhand, karela ki sabzi(bitter gourd vegetable) and daal(pulses). A truly relished meal!!!! I then topped it off with vanilla flavoured milk that I made with the vanilla that I had brought back from Kerala :) Ah! End of a really nice trip.... :) :)