Thursday, October 30, 2008
Geeks just wanna have fun
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
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!
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!