Thursday, October 30, 2008

Geeks just wanna have fun

A computer is truly the greatest geek toy ever invented. It is like an erector set to the googleplex power. Being "forced" to earn a living making virtual toys for others to use rather than spending ones days exploring this toy's possibilities for my own edification can be truly depressing sometimes. Maybe not as depressing as having to sell used cars or life insurance to feed one's family but close. I probably should be grateful I have a job that involves these toys especially in this economy.

I guess I just feel like being a whiner today in lieu of a useful blog post. Go ahead and slam me in the comments.

Tuesday, October 7, 2008

More Programmers = More Code

What do you get when you throw lots of programmers at a problem? You get lots of code! That's what programmers do, duh. It does not matter how simple or complex the problem is. For any given size problem, more programmers will mean more code. That is more code to debug, more code to test, more to maintain. More, more, more. Eventually this will require even more programmers and the cycle continues until the project collapses.

And it is even worse if you only hire the best and brightest programmers (don't we all!!). They write code faster! And it will be more complex than a dullard programmer because good programmers like to write general solutions.

Rich companies like Microsoft can keep this going for some time. However, you see the result in Vista and Office. Bloat, bloat, bloat.

What do you do if you have a problem that would take 12 months for 2 programmers but you want it done in 6. Hire 2 more programmers? Hire 4 more programmers? Big mistake! First off, it ain't gonna happen in 6 months no matter what you do if it is really a 12 month problem. If you must cover your ass as a manager and claim you used all your resources to make it happen in 6 months, I suggest the following.

Put 2 of the best programmers you have on the project. Make sure they like each other and think alike about software design. They are the leads. Only the leads will write code that will go into production.

Use all your remaining dollars to hire programmers who will support the leads but NOT write production code unless it is a piece of boiler plate delegated to them by one of the leads. What these junior developers do is write and execute unit tests for the leads. They write test tools when appropriate. They participate in code reviews. They are not slaves but future leads in training. Or maybe they are not future leads in training. Maybe they are salves. That's okay, mediocre programmer's need to eat to.

Some bigger projects may need 4 leads or even 6. If you have more than that your project is DOA and you better convince someone to spilt it up. If they won't, I'd find another place to work. That's better than being canned or losing all you hair/sleep/health over a doomed project. And trust me, it is doomed.

Wednesday, October 1, 2008

Let's Make a Deal - Let Monty Rest!

Some "solved" problems just never go away. Perpetual Motion machines is one example. Another example is the Monty Hall Problem. There is presently a mini-debate in the discussion area of Scientific American's How Randomness Rules Our World and Why We Cannot See It with a significant number of adamant doubters of the standard result that states it is better to switch if Monty shows you a goat.

This problem is amazingly obvious to understand once you analyze it correctly and remove certain ambiguities from the problem statement. Here's my analysis and some Mathematica simulations to add some weight (as if any is needed).

Okay, we all can agree that the probability of NOT picking the DREAM VACATION is 2/3, right? There are two GOATS and one DREAM VACATION.

Now, when Monty shows you the remaining door with a GOAT he just beamed you some very significant information. He's told you that if you picked a GOAT then the probability of getting a DREAM VACATION is 1 if you switch! We already know the probability you picked a GOAT is 2/3 so after he gives you this new info your probability of winning is now 2/3. So switch for GOAT's sake!! If you don't switch, your probability is just 1/3.

Here is a Mathematica program for the non-believers.

GOAT = 0; (* Goat worth zero *)
VACATION = 1; (* Vacation worth one*)

makePrizes[] := Module[{},Switch[RandomInteger[{1,3}],
1,{GOAT,GOAT,VACATION},
2,{GOAT,VACATION,GOAT},
3,{VACATION,GOAT,GOAT}]]

randomPick[doors_List] := Module[{},RandomInteger[{1,Length[doors]}]]

strategy1VS2[trials_Integer] :=
Module[{winnings1=0, winnings2=0, firstPick, secondPick, doors, doors2},
SeedRandom[];
Do[doors = makePrizes[];
firstPick = randomPick[doors];
(*winnings of person who keeps first pick*)
winnings1+= doors[[firstPick]];
(*delete first pick from choices*)
doors2 = Drop[doors,{firstPick}];
(*delete goat from remaining*)
doors2 = Drop[doors2,Position[doors2,GOAT][[1]]];
(*Always pick remaining prize *)
secondPick =doors2[[1]];
(*winnings of person who switches*)
winnings2+= secondPick,{trials}];
{winnings1,winnings2}]

(*Run simulation 10000 times. *)
strategy1VS2[10000]
{3356,6644}


The result {3356,6644} means keeping first choice only paid 3356 over 10000 runs but switching paid 6644!

Now, there are ASSUMPTIONS here (there always are). One assumption is that on each run the position of the prize changes. It turns out that keeping the prize always in any particular door for the entire simulation does not matter (as long as the contestant does not have the information, obviously!)

strategy1VS2A[trials_Integer,init_List] :=
Module[{winnings1=0,winnings2=0,firstPick,secondPick,doors,doors2},
SeedRandom[];
Do[doors = init;
firstPick = randomPick[doors];
(*winnings of person who keeps
first pick*)
winnings1+= doors[[firstPick]];
(*delete first pick from choices*)
doors2 = Drop[doors,{firstPick}];
(*delete goat from remaining*)
doors2 = Drop[doors2,Position[doors2,GOAT][[1]]];
(*Always pick remaining prize *)
secondPick =doors2[[1]];
(*winnings of person who switches*)
winnings2+= secondPick;,{trials}];
{winnings1,winnings2}]


strategy1VS2A[10000,{GOAT,GOAT,VACATION}]
{3316,6684}

strategy1VS2A[10000,{GOAT,VACATION,GOAT}]
{3267,6733}


strategy1VS2A[10000,{GOAT,GOAT,VACATION}]
{3382,6618}


The other assumption is that your not forced to switch before seeing the goat. This IS important!!

strategy1VS2B[trials_Integer] :=
Module[{goatPositions,pos,winnings1=0,winnings2=0,firstPick,secondPick,doors,doors2},
SeedRandom[];
Do[doors = makePrizes[];
firstPick = randomPick[doors];
(*winnings of person who keeps first pick*)
winnings1+= doors[[firstPick]];
(*delete first pick from choices*)
doors2 = Drop[doors,{firstPick}];
(*Randomly choose from remaing*)
secondPick =randomPick[doors2];
(*winnings of person who switches*)
winnings2+= doors2[[secondPick]];,{trials}];
{winnings1,winnings2}]


strategy1VS2B[10000]
{3373,3295}


So information has value, Duh!

So now that you have this information, become a believer, make the switch!