Thursday, February 8, 2007

Sick, plus ordered bell numbers

I've been sick the last few days. I did a hard run last Friday, had dinner with a friend, and woke up the next morning with the worst sore throat imaginable. Since then I've been battling with a nasty upper respiratory virus that has me hacking like a tuberculosis plagued sailor. I've mostly been in bed.

While in bed, I've been doing programming problems. Now that I am done with my job interviews at Yahoo and Google, I'm not sure I really need to practice problems, but I enjoy them immensely, and have been hanging out at the website TopCoder. It has become a replacement for the amount of time I usually spend online playing chess.

I've done hundreds of these problems, but one interesting one yesterday went something like this:


GEEK ALERT! I'm going to get technical on your ass, so don't feel obligated to continue reading.


Suppose you have N different objects and have been 
given some informationabout their ordering. The
information will be given as a vector<string>
facts whose elements will be of the form "A=B" where A
and B are integers between 0 and N-1 inclusive. "0=8"
means the 0th object is equal to the 8th object. Given
these facts you will return the total possible number
of distinct ways the objects could be ordered.

For example: N = 4 facts = {"0=2","1=3"} Possible
orderings: 0=2<1=3, 1=3<0=2, 0=1=2=3 In this case
there are 3 possible orderings, so you would return 3.
If no facts were given, there would be 75 possible
orderings. As seen above, the orderings described here
are total orderings. This means, for all pairs of
objects, the ordering is specified (one is less than
the other, or they are equal). Two orderings are the
same if all pairs of objects in each ordering have
exactly the same relationship.

I generally love probability problems, but it took me a while to figure this one out. It wasn't reasonable to loop through all possibilities since there could be billions. The problem reminded me of the problem trying calculating how many possible rolls there are with N number of K sided dice. In that problem you have K buckets and try to determine how many ways to fit the N dice inside of them. In our problem, however, the number of buckets aren't fixed.

A simplification of the problem is to ignore the facts. Actually, when you have a fact, you can just treat the resulting information as one number. So if you know that a==b, you can pretend you have one less number to work with. The simplified problem goes like this:
Given N numbers, how many ways are there to group 
them into sets. Each set will have equal signs
between it's members, and between the sets you
will place less than signs. The order of the sets
is important. The order of the numbers within a
set is unimportant.

I manually calculated the first few results, then came up with a mechanism for counting them which became a royal pain to implement programatically. The first few results for N items are: 1, 3, 13, 75, 541... After some frustration I hit the jackpot, a really cool website that allows you to look up integer sequences. I discovered that the sequence above lists the ordered Bell numbers also known as the Fubini numbers. There is also an interesting set of numbers called the unordered Bell numbers or just plain Bell numbers, which tells you the number of ways to group N items into sets when the order of the sets is unimportant. Information on calculating regular Bell numbers was abundant, but not ordered Bell numbers, which is what I needed.

After some more research I disovered something called Stirling numbers, or more specifically, Stirling numbers of the second kind. Stirling numbers form a table that looks like this:


n \ k 1 2 3 4 5 6
1 1
2 1 1
3 1 3 1
4 1 7 6 1
5 1 15 25 10 1
6 1 31 90 65 15 1


Note that we've labeled each row n, and each column k, so we can write S(n,k). S(5,2) is 15 for example. Each number can be calculated by taking the number above itself times k + the number diagonally northwest of itself. So S(n, k) = S(n-1, k) * k + S(n-1, k-1).

Why are Stirling numbers useful for calculating the ordered Bell numbers? It turns out that if you want to find an ordered bell number, you just have to pick the corresponding row of stirling numbers, and sum them, multipying each term by k factorial as you move across the row. For example to find the 4th ordered Bell number B(4), you would pick the 4th row of Stirling numbers and add as follows: 1 * 1! + 7 * 2! + 6 * 3! + 1 * 4! = 75. Magic!

This works because you are actually summing the combinations for different ways of grouping the numbers. It makes for some easy code. Since the internet seems void of code to calculate ordered bell numbers here's a rough snippet in case someone finds it useful:


...
//Get the ordered bell # using a stirling transform
long long fub = 0;
long long kFact = 1;
for(int k = 1; k <= n; ++k) {
kFact *= k;
fub += calcStirling(n, k) * kFact;
}
return fub;

...

static long long calcStirling(int n, int k) {
assert(n > 0);
assert(k > 0);
if (k == 1) {
return 1;
}
if (k == n) {
return 1;
}
long long result = calcStirling(n - 1, k - 1) +
k * calcStirling(n - 1, k);
return result;
}

Enough geeky math stuff. Next time I'll talk about my triathlon training.

Monday, February 5, 2007

Finding a Job

What is a job?

According to the Internet, a job is:
  • a piece of work, esp. a specific task done as part of the routine of one's occupation or for an agreed price.
  • a suffix that can be added to nearly any body part to create a sexual connotation.
  • a book of the Old Testament between Esther and Psalms.

There are good jobs, bad jobs, and jobs in between. My first job was working as a stable boy, shovelling horse shit 8 hours/day in 100 degree heat for minimum wage. I actually liked the job, as it gave me a chance to think, hang out with the horses, and made me really strong over the course of the summer. My worst job was working as a waiter for an extremely angry Italian owner who would yell and break things in the kitchen - I didn't work there long. My software engineering jobs have been good for many reasons, but I have had a tendency to burn myself out by working too many hours and placing extremely high expectations on myself.

Here are some things that good jobs seem to have in common for me:
  • I look forward to waking up and going to them in the morning.
  • They allow me to be creative and build things that I am proud of.
  • They provide me tools I need and help me set reasonable expectations for myself.
  • They surround me with competent people who I enjoy working with.
  • They challenge me and help me improve myself.
Bad jobs have many of the opposite characteristics:
  • They grind my efficiency to a halt for various reasons that they don't let me control - inadequate tools, constant meetings, a ridiculously long build process, or by giving me poorly designed and buggy software to build on top of.
  • They set unclear expectations and provide me with little feedback showing the value of my work.
  • They bore me by making me do endless repetitive tasks.
  • They surround me with incompetent or paranoid people.
  • They ask me to work on ideas or projects that I disagree with.
I got asked three questions today in an email from a prospective boss.
  • What are the top 3 things you would like to accomplish in life?
  • What would you like your career to look like in 4 years - what does the dream job look like then?
  • What are the 3 most important criteria of your next job?
These are good questions, and I am impressed that he asked them, as they show some savvy on his part, both because he seems to care about my goals and because he will get some insight into convincing me to work for him. If you are reading this, you should try answering those questions for yourself.

Here are my attempts at answers:

What are the top 3 things you would like to accomplish in life?

I'm not sure there is anything specific I need to accomplish to be happy. It is probably more important how I live my life and interact with others than what I accomplish. But if I had to choose 3 things to accomplish they might be the following:
  • I'd like to build something that effects many people and makes their lives better.
  • I'd like to find a spouse I love, have kids with her, and raise them well.
  • I'd like to create a means by which to teach others about my passions - specifically technology and the outdoors. I might do this by creating software, starting a summer camp, writing a book, or even becoming a teacher.

What would you like your career to look like in 4 years - what does the dream job look like then?

In four years I'd like to be able to say a couple things about my career:
  • I have a resume that will allow me to work for nearly any software company I'd like to in the world.
  • I have the skills, contacts, and personality to find, lead, and motivate other talented engineers to accomplish something that I believe in doing.
I'm not sure there is a specific dream job as there are many jobs I might like. I would love to be somewhere where I got to spend my days solving problems, where people liked working with each other, and where I am working on a product which I think is important and that many people will use including myself.

What are the 3 most important criteria of your next job?
  • I want to work somewhere where I will learn as much as possible.
  • I want to like the people I'll be working with.
  • I want to like the products I'm building and be able see a practical path towards their successful widespread adoption.


Napolean Dynamite said "Girls only want boyfriends who have great skills." He must have gotten companies and girls confused, but that's understandable. It's nice to have skills either way.

Prelude to the Adventures

“Remember what Bilbo used to say: It's a dangerous business, Frodo, going out your door. You step onto the road, and if you don't keep your feet, there's no knowing where you might be swept off to.” --J.R.R. Tolkien

I like adventures. I am always excited to try things that are new, novel, and that test my limits. Here are a few of the more adventurous things I've done in my life:
  • Leaving school to write and sell genetics software while saving money by living out of a van.
  • Moving from North Carolina to San Francisco to find work at a computer startup and quickly taking a leadership role there.
  • Spending time on numerous challenging athletic accomplishments - running races, participating in triathlons, and backpacking throughout California and on the east coast.
  • Taking a year off work to travel, hike the Pacific Crest Trail, and make money playing Poker.
  • Experimenting with freelance software development with my company Adventure Support.
  • Joining Google as a software engineer.

While none of the things I've done are exceptional, I do think a pattern emerges - I find myself the happiest when I don't quite know what the day or year will bring. I would be an unhappy farmer, but perhaps a spirited hunter gatherer.

Some recent things that I have been excited about include:
  • My current work at Google. I have tons of respect for what the company is doing, and the fact that I can affect so many people there.
  • Triathlons. I've been doing some triathlon training in hopes of doing a half Ironman next year
  • Kiteboarding. I really want the season to pick up so that I can get better at this insanely fun sport.

I'll be blogging about these intentions, as well as other ideas, so stay tuned.