Cyclic Linked List – Python function to find the node at the start of the loop

July 18, 2010 – 11:01 pm

I’d blogged previously about writing a python function to find out whether a linked list is acyclic or not – it’s worth a read before tackling this one.

Problem: Given the head node of a cyclic (or circular) linked list, write a function to return the node that is at the start of the loop.

A cyclic linked list would look something like this:

A->B->C->D->E->F->C

In the case above, A is the head node, and C is the node at the start of the loop.

There’s a few things to get your head around before the code below will make sense.

If the fast and slow pointers were enter the start of the loop at the same time, the fast pointer will catch up to the slow pointer when the slow pointer has gone around the loop once and is back at the start again.

If the fast pointer has a head start – that is it’s inside the loop already by the time the slow pointer gets to the start – then the fast pointer will catch up to the slow pointer before the slow pointer gets around once. In fact, it will catch up to it x nodes before the start node, where x is the number of node head start it had. So if the fast pointer is 3 nodes ahead when the slow pointer gets to the start of the loop, the fast pointer will catch up to it when the slow pointer is 3 nodes from reaching the start again.

How do we know how much head start the fast pointer had? Well, if you think about it, the length of the linked list before the start of the loop is effectively the head start the fast pointer gets (the fast pointer is always the same distance from the slow pointer as the slow pointer is from the head).

So as soon as the fast pointer catches up to the slow pointer inside the loop, we can set the slow pointer back to the head, and walk both forward a step at a time until they meet again – at the start of the loop!

def startOfCyclicLoop(head):

    """
    >>> e1=Element(1)
    >>> e2=Element(2)
    >>> e3=Element(3)
    >>> e4=Element(4)
    >>> e5=Element(5)
    >>> e1.next=e2
    >>> print startOfCyclicLoop(e1)
    None
    >>> e2.next=e3
    >>> e3.next=e4
    >>> e4.next=e5
    >>> print startOfCyclicLoop(e1)
    None
    >>> e5.next=e3
    >>> print startOfCyclicLoop(e1)
    3
    >>> e5.next=e4
    >>> print startOfCyclicLoop(e1)
    4
    >>> e5.next=e2
    >>> print startOfCyclicLoop(e1)
    2
    """
    slow=head
    fast=head
    while fast!=None and fast.next!=None:
        slow=slow.next
        fast=fast.next.next
        if (fast==slow):
            slow=head
            while (fast!=slow):
                slow=slow.next
                fast=fast.next
            return fast
    return  None

class Element:
    def __init__(self,data,next=None):
        self.data=data
        self.next=next
    def __str__(self):
        return str(self.data)

if __name__ == "__main__":
    import doctest
    doctest.testmod()

Puzzle – Hands on a Clock

June 6, 2010 – 12:26 am

For a given time, what will be the angle between the hour and minute hands on a clock?

This is rather a long winded way of solving this, so please let me know if you have something shorter.

The angle of the minute hand (from 12 O’clock):
= (minutes / 60) * 360

The angle of the hour hand (from 12 O’clock) is the angle of the hour plus an adjustment for the minutes:
= (hours / 12) * 360 + (minutes / 60) * (1 / 12) * 360

So to get the angle between them we subract the two, and get:
= (hours / 12) * 360 + (minutes / 60) * (1 / 12) * 360 – (minutes / 60) * 360
= (hours * 30) + minutes * .5 – minutes * 6
= hours * 30 – minutes * 5.5

Any angle over 180 we can subtract from 360 to get the shortest angle between them.

Anagrams – Python

June 4, 2010 – 11:56 pm

Write a Python function to find all the anagrams for each of a supplied list of words. For the word dictionary to find the anagrams you could use the one found on Unix or OS X boxes at /usr/share/dict/words. So for example:

>>> for group in anagrams(['dog','cat','horse']):
...     print group
...
['dog', 'god']
['act', 'cat']
['horse', 'shoer', 'shore']

When called without a parameter, make the function return a list of all the anagram groups in the word dictionary, ordered by the group of anagrams with the most words:

>>> for group in anagrams():
...     if len(group)>6: print len(group), group
...
9 ['ester', 'estre', 'reest', 'reset', 'steer', 'stere', 'stree', 'terse', 'tsere']
9 ['angor', 'argon', 'goran', 'grano', 'groan', 'nagor', 'orang', 'organ', 'rogan']
9 ['caret', 'carte', 'cater', 'crate', 'creat', 'creta', 'react', 'recta', 'trace']
8 ['leapt', 'palet', 'patel', 'pelta', 'petal', 'plate', 'pleat', 'tepal']
8 ['laster', 'lastre', 'rastle', 'relast', 'resalt', 'salter', 'slater', 'stelar']
7 ['dater', 'derat', 'detar', 'drate', 'rated', 'trade', 'tread']
7 ['easting', 'gainset', 'genista', 'ingesta', 'seating', 'signate', 'teasing']
7 ['darter', 'dartre', 'redart', 'retard', 'retrad', 'tarred', 'trader']
7 ['least', 'setal', 'slate', 'stale', 'steal', 'stela', 'tales']
7 ['atle', 'laet', 'late', 'leat', 'tael', 'tale', 'teal']
7 ['alem', 'alme', 'lame', 'leam', 'male', 'meal', 'mela']
7 ['lapse', 'salep', 'saple', 'sepal', 'slape', 'spale', 'speal']
7 ['armet', 'mater', 'metra', 'ramet', 'tamer', 'terma', 'trame']
7 ['argel', 'ergal', 'garle', 'glare', 'lager', 'large', 'regal']
7 ['aldern', 'darnel', 'enlard', 'lander', 'lenard', 'randle', 'reland']
7 ['alert', 'alter', 'artel', 'later', 'ratel', 'taler', 'telar']
7 ['arist', 'astir', 'sitar', 'stair', 'stria', 'tarsi', 'tisar']
7 ['aril', 'lair', 'lari', 'liar', 'lira', 'rail', 'rial']
7 ['asteer', 'easter', 'reseat', 'saeter', 'seater', 'staree', 'teaser']
7 ['arpent', 'enrapt', 'entrap', 'panter', 'parent', 'pretan', 'trepan']
>>>

Can you think of the most elegant and efficient (dare I say pythonic?) way to implement the anagrams function?

:

def anagrams(wordsin=None):
    f=open('/usr/share/dict/words')
    ana=dict()
    for word in f.readlines():
        ana.setdefault(''.join(sorted(word.rstrip())),[]).append(word.rstrip())
    if wordsin!=None:
        return [ana.get(''.join(sorted(wordin)),[]) for wordin in wordsin]
    else:
        return sorted(ana.values(), key=lambda(v): (len(v)),reverse=True)

Puzzle – Birthday pairings

April 30, 2010 – 2:20 pm

Here’s two classic birthday puzzles:

How many people do you need in a room to have a better than 50% chance of finding at least one shared birthday among them?

Like a lot of these problems, it’s easier to first find the chances of the proposition not happening – that is of not finding a shared birthday.

For this problem, I like to imagine that I have a bunch of 365-card decks. I deal one card from each deck. What are the chances that I haven’t dealt the same card after after dealing from r decks? You can see that this is a good analogy for our problem. Looking back at the previous post on dealing a perfect hand may be a good primer for what follows.

The answer to our card analogy is to take the number of ways I can deal the cards (one from each deck) and get no duplicates divided by the total number of ways I can deal the cards. From the first deck, I have 365 ways to deal one card. From the second deck, I have 364 ways to deal one card and not have duplicates. From the third deck, there are 363 ways, and so on until I get to 365-r+1 ways. So the number of ways I can deal cards without duplicates is:

= 365 * 364 * … * (365-r+1)
= 365! / (365-r)!

Now lets work out how many ways there are to deal the cards without restrictions. The answer is simply:

= 365 ^ r

So now, the probability of not dealing any duplicate cards (and also the chances of not finding anyone with a shared birthday) is:

= (365! / (365-r)!) / 365 ^ r

I was a little stumped at how to solve this, except through some trial and error. Even then, 365! seems to make calculators, or even trusty google, blow up. We can use Sterling’s approximation to find that:

ln(365!) = 1792.33142
ln((365-22)!) = 1663.17935
ln((365-23)!) = 1657.34162

So for r=22, our probability of no shared birthdays:
= e ^ (1 792.33142 – 1 663.17935) / 365 ^ 22 = 0.524310203

For r=23:
= e ^ (1792.33142 – 1657.34162) / 365 ^ 23 = 0.492707724

Now remember that this is for finding no shared birthdays. To have at least 1 shared birthday, we need to subract from 1.

So for r=22, the chances of finding at least 1 shared birthday are:
= 1 – 0.524310203 = 0.475689797

For r=23, the chances are:
= 1 – 0.492707724 = 0.507292276

So you can see that it takes at least 23 people in a room to have a greater than 50/50 chance of finding a shared birthday.

By the way, to get the Stirling approximation of ln(365!) I typed the following into google:

365 * ln(365) – (365) + ln(365)/2 + ln (2*pi) / 2)

How many people do you need in a room with you to have a better than 50% chance of finding someone who shares your birthday?

This one’s a little simpler than the first. Again, it’s easier to first find the probability of no one having your birthday. Let’s imagine people walking in to a room where you are. The first person has a 364/365 chance of not having your birthday. And it’s the same for all subsequent people who walk into the room. So the chances of no one sharing your birthday after r people have walked in are:

= (364/365)^r

So the chance that at least one person shares your birthday is:

= 1 – (364/365) ^ r

Let’s find r when the equation is 1/2, representing the at least 50% chance we were looking for:

1/2 = 1 – (364/365) ^ r
(364/365) ^ r = 1/2
r * log (364/365) = log (1/2)
r = log (1/2) / log (364/365)
r = 252.651989

So you need to have at least 253 people with you in a room to have a better than 50/50 chance of finding someone sharing your birthday. It’s quite amazing how different this answer is to the answer for the first part.

Puzzle – A perfect hand

April 29, 2010 – 2:32 pm

You deal the first 13 cards from a well shuffled, 52-card deck to someone. What are the chances the 13 cards you deal are of the same suit?

There’s a couple of ways to do this – both incorporate useful techniques for solving these kind of problems.

The first way is just to look at the first 13 cards dealt and work out how many ways there are to deal a single-suit hand, and divide this by the number of ways there are to deal any hand.

There are 52 ways you can deal a first card. There are then 12 ways you can deal a second card if we restrict it to the suit of the first card. So we now have 52 * 12 permutations. With the third card, we’re up to 52 * 12 * 11 permutations. So we can see that:

Ways to deal a single-suit 13 card hand = 52 * 12!

Using the same logic, we can see that:

Ways to deal any 13 card hand = 52 * 51 * 50 * … * 40. This equals 52! / 39!. (Hopefully this is clear – the remaining sequence to finish making 52! is 39!).

So the probability of dealing a single-suit 13 card hand = (52 * 12!) / (52! / 39!) = 12! * 39! / 51!

Is there a way to work this out without blowing up our calculator? We can go old school and get out our factorial log tables.

The log of the answer equals the log of (12! * 39! / 51!). If you remember your log rules, this is the same as log(12!) + log (39!) – log(51!). If you don’t have log of factorial tables you can type that equation into google and it magically gives you the answer. So you get:

log(12!) + log (39!) – log(51!) = -11.200723

So the log of our answer = -11.200723. Now let’s take the antilog to get our answer:

x = 10 ^ -11.200723
x = 6.299078 * 10 ^ -12

This is the probability. Take the reciprocal to get the odds to 1 against:

1 in 158,753,387,100

Holy cow – that’s what in Australia we call between Buckley’s and none.

The second way to do this is using some combinatorial tricks across the entire deck.

The first thing you have to know is: if I have a group of things of size n, now many ways are there to select a subset of size r. It turns out to be: n! / (r! * (n – r)!). So for example if I had 5 balls, I could arrange 2 balls out of the 5 in: 5! / (2! * 3!) = 15 ways.

As a side note – and I cover this more at the end of this post – I’m treating this as an order doesn’t matter, repetitions not allowed arrangement.

How does this help us in this problem? Let’s think of the number of ways that I can select 13 cards from this deck. The order in which the cards are selected doesn’t matter. The answer, following our example above would be 52! / (13! * 39!). Out of all of these possibilities, how many of these give us 13 cards a particular chosen suit? The answer is only 1. The reason is that there’s only 13 cards of the chosen suit, and the arrangement I’m looking for has all of them. And since order doesn’t matter, there’s only one arrangement that has all of these 13 particular cards.

So dividing the number of arrangements with 13 cards being our chosen suit by the total number of arrangements gives us: 1 / (52! / (13! * 39!))

Now we have to multiply this by 4, as we have 4 suits.

= 4 * 1 / (52! / (13! * 39!))
= 4 13! * 39! / 52!

We can see that this becomes our original answer above:

12! * 39! / 51!

It’s probably a good idea at this point to formalize a little the definitions of permutations and combinations, as this is what the above has been all about.

Permutations are when the order of the arrangement does matter – the order is a factor in making the arrangement unique.

Combinations are when we want to get the number of arrangements without regard to order. So we can treat the arrangements as buckets we can shake up and it’s still the same arrangement.

Within these, we can also allow repetitions or not. In other words, in a given arrangement, can a particular item be used more than once?

Some examples will help:

Combinations

Repetitions allowed: Let’s say you’re ordering a sandwich at Subway and can choose 3 meats out of a possible 5. If you love salami, you could chose salami, salami and salami for your meats. And we don’t really care what order we get the meats in the sandwich – for example, bologna, salami, bologna is the same as salami, bologna, bologna.
No Repetitions: Let’s say Subway had only one of each of the meats left – so you couldn’t choose the same meat twice. Another good example is a lottery where you need to match 6 numbers drawn from a pool of 40. Once a number is drawn it doesn’t go back in to the pool.

Permutations

Repetitions: the classic example is that of a combination lock (which should really be called a permutation lock!). Order does matter, and repetitions are allowed as your combination could be 7777.
No Repetitions: How many ways are there to get the first 3 positions in a 100 person race? Order matters, and you can’t have the same person in more than one position.

The formulas:

Permutation, repetition: n ^ r
Permutation, no repetition: n! / (n-r)!
Combination, repetition: (n + r – 1)! / (r! * (n – 1)!)
Combination, no repetition: n! / (r! * (n-r)!)

It’s interesting to note that in the above, the combination no repetition case is just the permutation no repetition case divided by r!. You can see this by thinking that for arrangements with 3 elements, there will be 3! more ways to arrange them if we care about order as in the permutation case than in the combination case.

The combination no repetition case is probably the most common and comes up in card-dealing problems and the like. It is sometimes called the “n choose r” case – or nCr, and also known as the “Binomial Coefficient”.

The combination with repetition case seems the most difficult to intuitively understand.

Puzzle – Patience is a virtue?

April 25, 2010 – 3:08 pm

Let’s say you’re playing a coin-tossing game. You start with $10 and are looking to double your money. The game is very simple: you pick an amount to wager on each toss, and if you toss heads you win the amount you wagered (as well as keeping the wagered amount), and if you toss tails you lose the amount you wagered. If you get to $0 you go bust and can’t play anymore. Moreover, when you get to your $20 target, you stop playing and take your winnings.

You take a bold approach and decide to wager your entire $10 on the first toss. You have a 50/50 chance of doubling your money, and whether you do or go bust will be determined on the first toss.

Would it have been better to take a more patient approach and only bet $1 on each toss?

You can probably answer this quickly just by thinking about the symmetry of the problem. In the patient approach, you have an equal chance of gaining or of losing $1 at each turn. You are the same number of steps from going bust as you are from doubling your money. So, just as with the bold gambler, your chances of doubling your money will be 50/50.

Now let’s say you start with $10 and want to get to $20, but this time the coin is weighted in your favor and you have a 2/3 chance of rolling heads. Similarly, let’s say you’re betting on even/odd in roulette where you have an 18/38 chance – slightly less than half – of winning on each roll. In these cases, is it better to be a bold gambler or a patient gambler?

Before answering this problem it’s useful to read and understand the previous post http://rebrained.com/?p=237.

Let’s call P the probability that we win this game (by reaching $20 before we go bust) and 1-P the probability that we’ll lose this game (by going bust before ever reaching $20). We’ll also call x our starting amount ($10 in this case) and y our target amount ($20 in this case).

Here’s the key insight: if this game kept going even after you’d reached the the target, there would be two ways to eventually go bust – never reaching the target, or reaching the target and then going bust.

Remember from the prior post that from any starting position x, the chances of eventually going bust if we don’t stop at a target amount are ((1-p)/p)^x.

In other words the probability of eventually going bust from our starting position if we didn’t stop after reaching our target (which we get from the above formula) is equal to the probability of eventually going bust without ever reaching our target (which is effectively 1-P, the probability of losing the game), plus the probability of reaching the target (which is P, the probability that we win the game), and then keeping going from the target and eventually going bust from there (which using the above formula we know is ((1-p)/p)^y.

So we can write:
((1-p)/p)^x = (1-P) + P * ((1-p)/p)^y

With some algebra you get the following:
P = (1 – ((1-p)/p)^x)) / (1 – ((1-p)/p)^y))

Something strange happens here when we plug in p=1/2 into the above formula – we get an indeterminate 0/0. To understand what is going on and how to solve this, read L’Hopital’s rule in wikipedia. Using this rule you’ll find that the answer for the p=1/2 case is that P = x/y, or 1/2.

So in the case of the fair coin, as per our argument from symmetry, it makes no difference whether you’re a bold or patient gambler. But what if the coin is weighted?

If p=2/3, the bold gambler has a has a 2/3 change of winning. Using the above formula, the patient gambler’s chances of winning are almost certain – something like 99.9%.

In the case of p=1/3, the bold gambler has a 1/3 chance of winning the game. The patient gambler’s chances of winning are vanishingly small – something like 0.1%.

What about the roulette case? From the above, we can probably suspect that where p is less than 1/2, the patient gambler’s chances of winning plummet much more quickly than the bold gambler’s chances.

In fact, while the bold gambler’s chances of winning are 18/38 – or something like 47% – the patient gambler’s chances of winning are only about 26%.

Puzzle – Will the gambler go bust?

April 23, 2010 – 3:09 pm

Let’s say that you’re playing a coin-tossing game, and you start with $1. You keep tossing forever, winning $1 if you toss heads, and losing $1 if you toss tails. What are the chances you’ll eventually go bust (get to $0)? What are the chances you’ll eventually go bust if the coin was weighted and tails only came up 1/3 of the time?

Let’s call p the chances of winning a dollar on any given toss, and (1-p) the chances of losing a dollar. Also, lets call P the chances of eventually going bust from our starting $1 position.

Imagine you managed not to go bust on the first toss, and are about to take the second toss. At this point, there are two possibilities – that at some point in the future you’ll move back to having $1, or that you’ll never move back to $1.

Here’s where a simple but clever insight can lead to this problem magically solving itself: when you’re at the $2 position, the probability of eventually moving back to $1 is the same as the probability you had of eventually moving to $0 (and going bust) when you started the game. You can see that it’s the same situation, it’s effectively just been transposed.

So the probability of eventually going bust at the beginning of the game (which we’ve defined as P) is equal to the probability on the first throw of tossing a tail (1-p), or tossing a head (p) and then going bust from the $2 state. The probability of going bust from the $2 state is the probability of eventually going back to the $1 state (which we worked out is P) and then eventually going bust from the $1 state (also P).

We can write the above like this:

P = (1-p) + p * P^2

We can solve this algebraically to have two solutions for P: 1 and (1-p)/p.

There’s some interesting conclusions from this:
- Without even the formulas we can see that if p = 1, we’ll keep winning $1 each time and the chances of ever going bust (P) will be 0. By the same token, if p = 0, then we’ll directly go bust so P will be 1.
- For p = 1/2, the formula will give 1. This means that for a fair coin, you’re guaranteed to go bust if you play long enough.
- For p < 1/2, the formula gives a result greater than 1, which is invalid. But clearly you'll be guaranteed to go bust in this case as well.
- For p > 1/2, the formula will give a probability ranging from 1 to 0. When p = 2/3 (as in our question above) then we have a 50/50 chance of eventually going bust.

What if you started with $2 – what are the chances you’ll eventually go bust?

What we worked out in the previous section is that the probability of eventually getting to $1 less than what you started with is 1 if p is smaller than or equal to 1/2, or (1-p)/p if p > 1/2.

So if you start with $x, and p is greater than 1/2, then your chances of going bust will be ((1-p)/p)^x.

Puzzle – A safe place to drop an egg

April 11, 2010 – 4:31 pm

Let’s say you need to find out the highest floor in a 100 story building from which you could safely drop an egg without it breaking. What’s your strategy to minimize the maximum (worst case) number of drops you have to try?

If you just had one egg with which to conduct your experiment, you’d have to start at floor one, and go up floor by floor looking for the first floor at which your egg broke until you reached floor 100. So your maxim number of drops would be 100.

What would be the worst case number of drops if you could use two eggs?

With two eggs you can be cleverer, and drop the first egg at floor 50, and effectively divide the floor space in half for your second egg.

You could also drop the first egg at floor 10, then assuming it doesn’t break, floor 20, 30, and so on. As soon as it broke, you’d try the 9 floors underneath with your second egg. So worst case if you get all the way to floor 100 before it breaks, then start at floor 91 with the second egg and get all the way to floor 99, then the total worst case drops is 19.

Can we do better?

Picking 10 as number of floors to skip with the first egg is not particularly efficient in dividing the floor space because if the first egg breaks on floor 10, the worst case is 10. But if the first egg breaks on floor 20, then the worst case is 11. As we saw, by the time you get to floor 100 your worst case is 19. The most efficient solution will be when no matter where the first egg breaks, our worst case stays the same.

To do that we could say that we’ll start with our first egg at floor 10, but the second drop will be on floor 19, preserving our 10 drop worst case. The problem you’ll find is that you end up reducing the spacing to 1 before you get anywhere close to floor 100. By trial and error you can find the best number to start with, and it turns out to be 14:

14, 27, 39, 50, 60, 69, 77, 84, 90, 95, 99, 100.

Is there a formula we can use to work this out, so we could do it for any number of floors?

Let’s look at the number of floors we skip at each turn:

n, n-1, n-2, n-3 … 1

Flipping that around, we have:

1, 2, 3, 4….. n.

We also know that the sum of the number of floors skipped will equal the total number of floors.

We know that the sum of a sequence like the above is (n+1) * n/2. You can see this if you pair the first and last numbers, the the second and second to last, etc.

So if we say h is the total number of floors in the building, we have:

h = (n+1) * n/2

So:

n^2 + n = 2h.

To solve for n, let’s use the completing the square trick:

n^2 + n + .25 = 2h + .25
(n+.5)(n+.5) = 2h + .25
n+.5 = sqrt (2h+.25)
n = sqrt(2h+.25) – .5

If we try this on our 100 floor problem, we get:

n = sqrt(200.25)-.5
n=13.65

So seeing as we need integer floors, we need 14 floors, which corresponds with our trial and error result.

I have to give props to Scruffy Pete for helping out on this one.

Alternating coin toss – redux

April 10, 2010 – 4:01 pm

I want to revisit a probability puzzle from a previous post: see problem #5 in http://rebrained.com/?p=20

You play a game where you alternate tossing a coin with a friend, and the first person to toss heads wins. But let’s make it a little more interesting by making the coin weighted, or biased, so that it lands heads only 25% of the time. If you were to start, what would be your chances of winning?

Let’s call the probability of tossing heads p and the probability of tossing tails q.

On the starter’s first toss, his chances of tossing heads are p. The chances he’ll toss heads on his second toss are q^2\times p. On his 4th toss it’s q^4\times p and so on.

So his chances of winning the game is the sum of the geometric progression p\times q^0\;+\;p\times q^2\;+\;p\times q^4\;+

Let’s use the shifting approach to solve this. The idea is to subtract out the first element, and then shift the rest of the elements to the left. So first subtract:
s-p\times q^0=p\times q^2\;+\;p\times q^4\;+

Now to shift the terms to the left, we need to divide by q^2
\frac{s-p\times q^0}{q^2}=p\times q^0\;+\;p\times q^2\;+

So…
\frac{s-p\times q^0}{q^2}=s
s=\frac{p}{1-q^2}

This gives us a general solution to the alternating coin toss problem. If we plug in the unweighted coin probabilities, we get s=\frac{2}{3} which is what we’d worked out before. For the case where the probability of tossing a head is 1/4, then we get s=\frac{4}{7}, which is the probability of winning for the starter.

Puzzle – Take your seats

April 7, 2010 – 1:22 am

Let’s say there are 100 people, including you, waiting to board a fully booked flight, each with an assigned seat. The first person to board doesn’t pay any attention to his assigned seat, and sits somewhere at random. Each of the subsequent people will sit in their assigned seat if they can, but if they find someone sitting there will pick another seat at random. You’re the last to board. What’s the probability you’ll get to sit in your assigned seat?

I like problems where I ponder for a while, am contemplating some tedious route to solve it, but then in the nick of time with a flash of insight see the answer. That was the case for me with this problem.

After starting toying with conditional probability, I realized that there are only two seats that really matter as each passenger boards: passenger #1′s seat (let’s call that seat #1), and my seat (let’s call that seat #100). As soon as someone sits in seat #1, it’s all over – I’ll definitely get to sit in my seat. Also, as soon as someone sits on seat #100, I’m done – there’s no way for me to sit in my seat. If any passenger chooses seat #1 or seat #100, we can essentially ignore all subsequent events.

Here’s the key: until either seat #1 or seat #100 is taken, each passenger that boards has the same probability of choosing seat #1 as they do seat #100.

That’s clearly the case for the first guy – he has a 1/100 chance of choosing seat #1, and a 1/100 chance of choosing seat #100. Now let’s take passenger #2. Regardless of what #1 has done, there’s be an equal probability he’ll choose seat #1 or seat #100. That probability is either going to be zero if he’s able to sit in his own seat, or if he can’t because passenger #1 has taken it, he’s equally likely to choose seat #1 or seat #100 (a 1/99 chance in either case). Let’s say we get to passenger #99. The only way the issue won’t have been already decided is if the choices he has left are seat #1 and seat #100. In that case, there’s still an equal probability (50/50 this time) he’ll choose seat #1 or choose seat #100.

So you can see from the above that the chance you get to sit on your own seat is 50/50, because as each passenger boarded there was an equal chance of the question being answered in either of the two possibilities.

Anybody have a different way to get the answer – or can get the answer by looking at the sum of conditional probabilities?

Puzzle – Leaning Tower of Pisa

April 2, 2010 – 10:55 pm

Let’s say you drop a ball from the Leaning Tower of Pisa, which is 179 ft high, and it bounces back 10% of the dropped height – 17.9 ft. Then on the second bounce it bounces up 10% again – 1.79 ft, and so on for ever. How far will the ball travel?

The first thing to realize is that this is a geometric progression which will yield a finite sum, even though it has an infinite number of terms. This idea of finite sums is the reason Zeno can walk across the room: http://en.wikipedia.org/wiki/Geometric_series#Zeno.27s_paradoxes.

Before answering the question it may be useful to recap geometric progressions from my previous post see the coin-toss puzzle answer.

In this problem, the total distance travelled by the ball will be: 179 + 179 * 2 * (1/10 + 1/100 + 1/1000…)

You may be able to see straight away that the sum of the progression is 1/9, and so the total distance 218 + 7/9.

But let’s do it using the standard approach:

Given that n in the progression will start at 1, we need to get our progression into the form:

<br />
\sum_{n=1}^\infty cr^{n-1} = \frac{c}{1-r}<br />

When we do this, we get the same answer as above:

<br />
distance =\;179\;+\;179\;*\;2\;*\;1/10\;*\;\frac{1}{1-\frac{1}{10}}\;=\;218\;\frac{7}{9}<br />

Puzzle – Break a stick to get a triangle

April 2, 2010 – 9:26 pm

I read somewhere this is a Google interview question:  Let’s say you drop a stick, breaking it randomly in 2 places, leaving you with 3 smaller sticks.   What’s the probability you can make a triangle out of the 3 sticks?

There are a number of ways to tackle this, including this very elegant solution: http://www.cut-the-knot.org/Curriculum/Probability/TriProbability.shtml. For the less elegantly inclined (and those as unlikely as me to be working at Google any time soon), here’s another way:

The first insight is that what you want to avoid is ending up with one really long stick and two short sticks – you need the shorter sticks to have a combined length greater than the longer stick. This effectively means that if you think about the stick as having two halves, then the two breaks need to be on opposite halves. The probability of the breaks being on opposite sides of the original stick is 50%.

The second insight is that when the breaks are on opposite halves, if you start from the outer ends of the original stick and measure the distance to each break, the sum of those two distances needs to be greater than 1/2 the length of the original stick. Otherwise we’d end up with two short sticks having a combined length less than the remaining stick. What’s the probability of this? The probability that two random numbers from 0 to .5 add up to more than .5 is 50%

So that’s a slightly long-winded way of arriving at the answer – which is that you have a 50% * 50%, or 1 in 4 chance, that you’ll be able to make a triangle.

Puzzle – 4 Bugs chasing each other

February 21, 2010 – 7:37 pm

Say there are four bugs standing at the corners of an imaginary 1m * 1m square.  Each of the bugs is facing the bug that is on the adjacent, clockwise corner from where they are.

At the same instant, each of the four bugs starts walking directly towards the bug they are facing at 1m per hour, and keeps walking directly towards that bug as that bug itself starts moving.  So the four bugs spiral towards the center of the square in a clockwise direction.

How long does it take for the four bugs to meet?

It’s clear that the bugs will meet at the center of the square.  The insight needed is that the bugs effectively stay in a square formation – a shrinking and spiraling square, but a square that is always centered on the original center. So regardless of where the bugs are in their spiral towards the center, they will always be moving 45 degrees to a line connecting where they are to the center.

Once you get your head around this, you can solve the problem by calculating the effective velocity towards the center:

</p>
<p>V_{center} = \cos\;45^\circ\;*\; V_{absolute}\\</p>
<p>V_{center} = \frac{1}{\sqrt(2)}\;m/hr</p>
<p>

The total distance towards the center from the starting position is: \frac{1}{\sqrt(2)}\;m

So it will take 1hr for the bugs to meet in the center.

Perhaps an easier way to think about this is that if you draw the square so it looks like a diamond and focus on the bug in the top corner, you’ll see pretty clearly that the line starting at the top corner and going 45 degrees from a vertical line down to the center, and ending so it’s horizontally level with the center is effectively a side of the diamond, which is one meter, and would take 1hr to walk.

There’s a way to arrive at the answer to this problem instantly and with no calculations – but does require somewhat of an a-ha moment.

A bug’s movement towards the bug it’s following is always perpendicular to the motion of the followed bug.  So in effect the movement of the followed bug has no effect on how far the follower has to travel to reach it or how long it will take, so the follower has to travel 1 meter, and will catch up to the followed bug in 1 hr.  A-ha!

Same principle as the above:  they stay in formation as they spiral to the center.   One bug is heading towards the other at 1 meter per hour.  In this case, the followed bug is making effective progress towards the follower at  cos(60), or .5 meters per hour.   So they have a combined speed of 1.5 meters per hour towards each other, so they should cover the 1 meter between them in 40 minutes.

Puzzle – Liars and Truthtellers

December 31, 2009 – 1:27 am

This is another probability question that seems straightforward but can be deceptive…

You’re an FBI agent and have been monitoring a large gang, and you know that 1/4 of its members always tell the truth, the rest always lie.  Then you get taken hostage by the gang, and two gang members are assigned to guard you.  You ask the first: ”Am I going to live?”  He answers “Yes.”  Then you ask the second the same question.  He also answers “Yes.”  What are your odds of living?


It can be tempting to say it’s the probability the first is telling the truth multipled by the probability the second is telling the truth, which would mean you have a 1/16th chance of living.

It’s not correct, however, because there’s another piece of information you have which is that they both gave the same answer.

Let’s look at the probability tree:

Guard 1       Guard 2      probability

T                  T               1/16

F                   F               9/16

T                   F               3/16

F                   T               3/16

The only two rows that apply to this problem are the first two – they can either both be telling the truth, or both be lying.  The chances they’re both telling the truth is:

\frac{\frac{1}{16}}{\frac{1}{16}+\frac{9}{16}}=\frac{1}{10}

So – what would your chances of living be if the first guard told you that you would live, but the second that you would die?

Look at the table in the answer above – at the rows where the answers were different… you’ll see that your chances are 50/50.

Puzzle – shortest road system

June 19, 2008 – 11:20 pm

Let’s say you’re contracted to build roads to connect four towns that are at the corners of an imaginary square with sides 1 mile. What’s the shortest length of road system you can build so that every town can get to every other town?


The first answers that come to mind for most folks are either to do a perimeter road with one one side left off which is 3 miles or to build roads in the shape of an X – which pythagoras tells is would be 2 * sqrt(2) = 2.828 miles.

Can you do better? Click on this link to see the answer.

You can work out the length using some basic calculus:

Call x the length of shared highway in the middle. So the total length of the road will be:

l\;=\;4\sqrt{(\frac{1}{2})^2 + (\frac{(1-x)}{2})^2}\;+\;x

Simplifying:

l\;=\;\sqrt{4 + 4(1-x)^2}\;+\;x

We’re trying to find xwhere l is the shortest. So we can differentiate l with respect to x, and set this equal to zero. Recall the chaining rule from high school?

\frac{dl}{dx}\;=\;\frac{1}{2}\;*\;(4 + 4(1-x)^2)^{-\frac{1}{2}}\;*\;8(1-x)\;*\;-1\;+\;1\;=\;0

\frac{1}{\sqrt{4 + 4(1-x)^2}}\;=\;\frac{1}{4(1-x)}

4 + 4(1-x)^2\;=\;\frac{1}{16(1-x)^2}

12(1-x)^2\;=\;4

1-x\;=\;\sqrt{\frac{1}{3}}

x\;=\;1-\sqrt{\frac{1}{3}}

And now we can substitute to find the total length of the road:

l\;=\;4 * \sqrt{\frac{1}{4} + \frac{1}{12}}\;+\;1\;-\;\sqrt{\frac{1}{3}}

l\;=\;4 * \sqrt{\frac{1}{3}}\;+\;1\;-\;\sqrt{\frac{1}{3}}

l\;=\;3 * \sqrt{\frac{1}{3}}\;+\;1

l\;=\;sqrt{3}\;+\;1

This works out to be 2.732 miles, a little better than our original X approach.

It’s neat that the angles turn out to be 120 degrees (as is shown in the link above). A colleague declared to me that this was ‘obvious’, but it’s not so obvious to me. Can anyone find a trigonometric way to solve this problem that doesn’t involve the calculus? Or at least provide an explanation for why the 120 degrees makes sense (other than that it’s a beautiful symmetry)?

Now, only because I’m a maniac and weirdly enjoying doing high school Calculus for the first time in a while, I’m going to pick x to be the distance from the shared highway to the edge of the square. So the shared highway length will be 1-2x.

l\;=\;4\sqrt{\frac{1}{4} + x^2}\;+\;1\;-\;2x

Simplifying:

l\;=\;\sqrt{4 + 16x^2}\;+\;1\;-\;2x

Now we differentiate:

\frac{dl}{dx}\;=\;\frac{1}{2}\;*\;(4 + 16x^2)^{-\frac{1}{2}}\;*\;32x\;=\;2

\sqrt{4 + 16x^2}\;=\;\frac{1}{8x}

4+16x^2\;=\;64x^2

4\;=\;48x^2

x\;=\;sqrt{\frac{1}{12}}

Now we can substitute for the length:

l\;=\;4 * \sqrt{\frac{1}{4} + \frac{1}{12}}\;+\;1\;-\;\sqrt{\frac{1}{3}}

Which we can see is identical to what we had above, so our length is again:

l\;=\;sqrt{3}\;+\;1

Puzzle – Clock

June 14, 2008 – 6:51 pm

It’s 3 O’Clock. What will be the time when the minute and hour hands are next in the same position (coincident)?

Answer

More puzzles…

June 14, 2008 – 5:12 pm

A few more brainteasers..

Some of these are from Heard on the Street – a book of interview questions for Quants I’m trying to get through. Well worth a read if you’re into this sort of thing – or if you ever want to pretend you’re a Quant at parties (oh yeah, that will really attract the ladies!)

1. Two ropes of different lengths, and you know that if you were to light either of them at one end it burns through in an hour. How can use use them to measure 45 mins?
Answer

2. Two identical jugs, one with water, one with vodka. You pour a bit of vodka into the water, mix it, then pour the mix back to get the jugs to their original volumes. What’s the relationship between the new concentration of vodka in the vodka jug and water in the water jug?
Answer

3. Imagine you’re an ant (you can walk on walls but not fly) and you want to get from a bottom corner of a cubic room (1*1*1) to the extreme opposite corner (farthest from you). What’s your shortest path to get there?
Answer

4. Let’s say you have a bunch of 1*1*1 mini-cubes that you’ve assembled into a 10*10*10 big cube. Now let’s say the whole outer layer of the big cube becomes damaged and has to be replaced – how many new mini-cubes do you need?
Answer

5. Say there are 100 lights with switches (initially off), and 100 people. The first person goes through and flips every switch (so all the lights are on). The second person flips every second switch, so at this point half the lights are off again. The third person every third switch, and so on. By the time the 100th person goes through he just flips switch #100. At the end, how many light bulbs are turned on?
Answer

Dice puzzle – redux

June 13, 2008 – 11:03 pm

I’d blogged previously about rolling a die and being given whatever you roll in dollars. You get given two more chances if you don’t like what you get the first time, or the second time, for a max of 3 rolls. What’s your strategy? You can see the answer in my previous post.

A couple of people have asked – what if there’s a pair of dice?

It’s the same principle. You could write all 36 permutations (but you’d live in fear you’ll be asked for a 3 dice solution). You know you can only roll a sum from 2 to a 12, and that you can get these sums from more than one combination of numbers on the dice.

You’ll see in the table below we again start by looking at the last throw. The expected payoff on the third throw is 7 (as you may have figured given the expected payoff for 1 die is 3.5). Following the same strategy as for the 1 die problem, for the second roll we pretend anything less than 7 is 7 for the purposes of figuring the expected payoff, which for roll 2 is 7.97. And so on for roll 1 which has an expected payoff of 8.54 (this is what you’d expect to win on average from this game).

 

 

 

 

 

 

 

 

 

 

 

 

 

So the strategy to maximize the expected payoff: on roll 1, stick with 8 or higher. On roll 2, stick with 7 or higher.

Mth to last – a recursive approach

June 12, 2008 – 7:17 pm

A collegue of mine was pondering the mthToLast problem for a LinkedList I’d blogged about previously and sent me the following IM message:

just a guess - but can you use  recursion to solve your link list m problem?
a method to track through the list which calls itself,
then when you get to the end start incrementing a counter,
and when it equals M return the value?

I think this is what he meant – it seems to work. Not as scalable as the trailing pointer approach in the previous post, but an interesting excerise in recursion. You find the size at the end, and return it all the way back. The code is a little messy with the 1 element case…anyone have a neater implementation?

class Element:
    def __init__(self,value,next=None):
        self.value=value
        self.next=next

def findMToLast(element,m,counter=1):
        """
        >>> e1=Element(1)
        >>> e2=Element(2)
        >>> e3=Element(3)
        >>> e4=Element(4)
        >>> e1.next=e2
        >>> e2.next=e3
        >>> e3.next=e4
        >>> findMToLast(e1,1).value
        4
        >>> findMToLast(e1,2).value
        3
        >>> findMToLast(e1,3).value
        2
        >>> findMToLast(e1,4).value
        1
        """
        if element.next==None:
            if m==1: mtolast=element
            else: mtolast=None
            if counter ==1: return mtolast
            return (counter,mtolast)
        (size,mtolast)=findMToLast(element.next,m,counter+1)
        if size-counter+1==m: mtolast=element
        if counter==1: return mtolast
        return (size,mtolast)

if __name__ == "__main__":
    import doctest
    doctest.testmod()

Reverse a string using recursion

June 12, 2008 – 1:52 am

Very basic – take a string and reverse it using simple recursion. I’m sure there’s a bunch of ways to do it, but like the fibonacci you should aim to be able to code this in about 30 seconds…

>>> def reverseString(str,loc=0):
	if loc>=len(str): return ''
	return reverseString(str,loc+1)+str[loc]

>>> reverseString("hello")
'olleh'

Another way:

>>> def reverse(str):
    if len(str)==1:
        return str
    else:
        return reverse(str[1:])+str[0]

>>> reverse('hello')
'olleh'
>>>

Ok, a little more interesting: let’s say we wanted to reverse the strings within words, but keep the words in the original order. An ugly implementation, again using recursion:

>>> def reverseWithinWords(str,loc=0):
	if loc>=len(str): return ('','')
	(revstr,revwords)=reverseWithinWords(str,loc+1)
	revstr=revstr+str[loc]
	if (str[loc]==" ")|(loc==0):
		revwords=revstr+' '+revwords
		revstr=''
	if loc==0: return revwords.strip()
	return (revstr,revwords)

>>> reverseWithinWords("hello my lovely")
'olleh ym  ylevol'

Now et’s say you were now asked to reverse the words, but keep the letter order the same – so for example “yes dark lord” becomes “lord dark yes”…
Answer


The quickest way to reverse a string is to use the slice function:

>>> 'abcdef'[::-1]
'fedcba'
>>>

Deep copy and recursive references

June 10, 2008 – 1:59 am

Quick one about coding a deep copy and avoiding recursive references…

Let’s say we have an instance a which has a reference to an instance b and we have to do a deep copy of a. To do this, we need a deep copy of b as well.

But let’s say b had a reference back to a.

Here it is in Python (I know Python has its own __deepcopy__() method but the below is for illustrative purposes).

class A:
    def __init__(self,b=None):
        self.b=b
    def deepcopy(self):
        newA=A()
        newA.b=self.b.deepcopy()
        return newA

class B:
    def __init__(self,a=None):
        self.a=a
    def deepcopy(self):
        newB=B()
        newB.a=self.a.deepcopy()
        return newB

Now let’s execute this:

>>> a=A()
>>> b=B()
>>> a.b=b
>>> b.a=a
>>> newA=a.deepcopy()

What happens? Not pretty – a recursion limit error.

To fix this, we can keep track in a as to whether that instance has already created a copy of itself, so when it is called back from b it can just return that instance. This is sometimes called the “memo” copy. See amended code below.

class A:
    def __init__(self,b=None):
        self.b=b
        self.memo=None
    def deepcopy(self):
        if self.memo==None:
            newA=A()
            self.memo=newA
            newA.b=self.b.deepcopy()
            self.memo=None
            return newA
        else:
            return self.memo

class B:
    def __init__(self,a=None):
        self.a=a
    def deepcopy(self):
        newB=B()
        newB.a=self.a.deepcopy()
        return newB

Now when we execute:

>>> a=A()
>>> b=B()
>>> a.b=b
>>> b.a=a
>>> newA=a.deepcopy()
>>> newA
<__main__.A instance at 0x00D53A30>
>>> newA.b.a
<__main__.A instance at 0x00D53A30>
>>> newA2=a.deepcopy()
>>> newA2
<__main__.A instance at 0x00D53AF8>
>>> newA2.b.a
<__main__.A instance at 0x00D53AF8>
>>> 

Note that the memo is removed just before the copy is handed back so that if you call deepcopy again you’ll get a new copy of a.

Bootstrapping Zero Curves

June 8, 2008 – 8:07 pm

A yield curve is a representation of what interest rates you could lock in today for investments over different periods. It’s effectively a set of yields for securities of different maturities (typically cash rates at the short end, futures and then swaps at the longer maturities – see the wikipedia entry). These yields are typically calculated from market prices using standard price/yield formulas.

The problem is that the quoted rates are from coupon paying securities and tell us the value of a series of cash flows, but they don’t tell us the rate for a cash flow at the maturity point independently of the other cash flows. So these rates don’t directly imply the present value of a dollar to be received at the maturity points – that is, they cant be used directly as discount rates.

A zero curve represents the set of interest rates assuming that there are no periodic cash flows – as though the rate reflects a single payment of interest and principal made at that maturity point on the curve. As such, the rate can directly provide the present value of a dollar received at these maturity points.

Let’s take a very simple example:

A yield curve with 3 points:
Year 1: 5%
Year 2: 6%
Year 3: 7%

This means if you invest $1:

  • For 1 year, you’ll receive 5% interest plus your principal – $1.05 – at the end of year 1.
  • For 2 years, you’ll get 6% annually, with your principal included at the end of year 2. So you will get $.06 at the end of year 1, and $1.06 at the end of year 2.
  • For 3 years, you’ll get $.07 at the end of year 1, $.07 at the end of year 2 and $1.07 at the end of year 3.

The key point here is that the 2 and 3 year rates effectively represent a coupon paying security. In the 2 year rate, $1 invested now for two years represents the combined PV of two cash flows. But what is the PV of just the second cash flow? If we can work this out, we’ll have a zero (or discount) rate at 2 years, enabling us to PV any money received 2 years in the future.

We know the PV of $1 received at the end of the first year using our basic time value of money formula:

PV = \frac{FV}{(1 + r)^n} = \frac{1}{(1 + .05)^1} = \frac{1}{1.05}

This is effectively the 1 year discount factor. So any monies received at the end of 1 year can be multiplied by this to get the PV. Building (or “bootstrapping”) the zero curve is obtaining these discount factors for all maturity points.

To get the zero rate, or discount factor, for the 2 year point, we can say that $1 invested today will equal the PV of 1st payment plus the PV of 2nd payment. So:

PV = 1 = (\frac{.06}{1.05}) + (\frac{1.06}{(1+r)^2}) (where r equals the 2 year discount factor)

Working this out, we end up with r_{\tiny{Z2}}=.0603 or 6.03%

For the 3rd year zero rate, we build on the above:

PV = 1 = (\frac{.07}{1.05}) + (\frac{.07}{(1+.0603)^2})  + (\frac{1.07}{(1+r)^3}) (where r equals the 3 year discount factor)

This gives us r_{\tiny{Z3}}=.07097 or 7.097%

Now we have our zero curve that we can used as discount rates for cash flows at the corresponding
maturities.

So the corresponding zero curve:
Year 1: 5%
Year 2: 6.03%
Year 3: 7.097%

It’s interesting to note that the zero rates are slightly higher than the yield curve rates when the curve is sloping upwards. If you have trouble seeing why think of an extreme case of a yield curve with 0% rate in 1 and 100% rate in year 2.

Another concept worth touching on here are the implied forward rates from these zero rates. Let’s say we invest $1 for 2 years under our zero rate, which is 6.03%. This would give us a return of:

FV = 1 * (1 + .0603)^2 = 1.124236

We could also have invested for 1 year, then take that return and lock in a forward rate for the second year (the rate at the end of year 1 for investing for year 2). Under the rules of arbitrage, this forward rate for year 2 needs to give us the same return as investing for 2 years using the 2 year zero rate. So:

FV = 1.124236 = 1.05 * (1 + r_{\tiny{1,2}}) where r_{\tiny{1,2}} is the forward rate for the second year

This gives an implied forward rate r_{\tiny{1,2}} = .070707 = 7.07%

You can keep building these implied forward rates for all future years using this technique.

The “Mathematical Constant” and Continuously Compouding Interest

June 8, 2008 – 12:28 am

One of the (many) aspects of the ”Mathematical Constant” e is that:

\lim_{x\to\infty} (1+\frac{1}{x})^x = e

This property makes e very useful for working on compounding interest problems. How so?

Let’s start with the basic time value of money formula giving the relationship between the PV (present value) and FV (future value) given R (the rate of interest):

FV = PV * (1 + R)^n

In the formula above n represents the number of compounding periods. Given normal conventions, this is typical represented as m * Y where m is months (or other periods – it represents how many chunks we divide the year into for receiving interest payments) and Y is years. Also, the R (or rate) above is normally quoted in years, so we should divide this by the months: R/m.

So now we have:

FV = PV * (1 + \frac{R}{m})^{mY}

We can make use of the e formula above if we want continuously compounding interest – that is where m is as high as possible, converging on \infty.

Let’s start by making x=\frac{m}{R} and we would get:

FV = PV * (1 + \frac{1}{x})^{x * YR}

We can now drop this into our formula for e given that we want m (or x, which is effectively our proxy for m) to approach \infty:

FV = PV * [\lim_{x\to\infty} (1+\frac{1}{x})^{x}]^{RY}

We can write this simply as:

FV = PV * e^{RY}

So if we invest $100 at 6.5% continuously compounding interest for a year, we will end up with:

FV=100 * e^{(.065*1)}=$106.72

Probability Puzzles…

June 1, 2008 – 11:52 pm

Some probability questions/puzzles:

1. I have two children. One of my children is a girl. What are the chances I have two girls?
Answer

2. There is a sixgun with two bullets in consecutive chambers pointed at your head. The bad guy spins it, then pulls the trigger. It clicks on an empty chamber. He then tells you that you have a choice: he pulls the trigger again or spins it first before pulling the trigger. Which to choose?
Answer

3. I guess I have to put the old three door problem in here. You’re at a game show, and the host tells you the car is behind one of the three closed doors – and to choose a door. Before he opens your chosen door, he opens one of the two remaining doors that he tells you he knows the car is not behind, and then gives you the choice of sticking with your original pick or switching to the other unopened door. Which do you do?
Answer

4. It’s your birthday, and a generous uncle tells you that he’ll give you in dollars whatever number comes up when you roll a die – so you will win between $1 and $6. He makes it more interesting – if you don’t like what you roll the first time, you can roll again. And if you don’t like that, you can roll one more time – for a maximum of three rolls. Note that if you choose to throw again, you can’t go back to an earlier better roll. What’s your strategy to maximize your winnings?
Answer

5. You take it in turns tossing a coin with a friend – you having the first toss – and keep going until one of you tosses heads and wins. What are the chances you’re the winner?

To answer question 5 it helps to know a little about geometric progressions. The chances of me winning are the sum of my chances at each toss which is: 1/2 + 1/8 + 1/32… The chances of my friend winning are 1/4 + 1/16 + 1/64… I’m not sure this is the most rigorous way to think about this, however we know that when r<1:

<br />
\sum_{n=0}^\infty cr^n = \frac{c}{1-r}<br />

and we also know that:

<br />
\sum_{n=1}^\infty cr^{n-1} = \frac{c}{1-r}<br />

So if you can get your progression into one of the two forms above, you can just apply the formula on the right hand side.

Now start looking at this from the point of view of the guy starting second. His first toss has a probability of \small1/2^2, his second toss \small(1/2)^4, his third \small(1/2)^6. So we can see that on his nth toss, his probability will be \small(1/2)^{2n} with n starting at 1.

We see from the above formulas that when we have n starting at 1 we need to get our progression into the form: {\small}cr^{n-1}.

So we need to expand as such:

(\frac{1}{2})^{2n} = (\frac{1}{4})^n = \frac{1}{4} * (\frac{1}{4})^{n-1}

Now we have c=1/4 and r=1/4 to plug in:

\frac{c}{1-r} = \frac{\frac{1}{4}} {1 - \frac{1}{4}} = \frac{1}{3}.

So of course, since someone has to win, the probability for the starter is 2/3.

But let's work this out. The starter's probability at toss n is \small(1/2)^{2n+1} with n starting at 0. Since n starts at 0, we need to get this into the form: {\small}cr^{n}. Expanding as above:

(\frac{1}{2})^{2n+1} = \frac{1}{2} * (\frac{1}{4})^{n}

Now we have c=1/2 and r=1/4 to plug in:

\frac{c}{1-r} = \frac{\frac{1}{2}} {1 - \frac{1}{4}} = \frac{2}{3}.


BinaryTree – Lowest Common Ancestor – Python

June 1, 2008 – 3:53 am

The last problem in the Trees chapter of Programming Interviews Exposed was about finding the lowest common ancestor between two nodes of a binary tree. Starting from the head, if you find that the nodes that you’re looking for straddle the node you’re on, then you’ve found your lowest common ancestor. If they’re both on one side or the other, grab your child on that side, and recurse. The key is realizing that when you go left (for example) there will be no result on the left branch bigger than the right’s universe.

def commonAncestor(node1,node2,head):
    """
    node1=Node(1)
    node4=Node(4)
    node3=Node(3,node1,node4)
    node7=Node(7)
    node5=Node(5,node3,node7)
    commonAncestor(node1,node7,node5).value
    5
    commonAncestor(node1,node5,node5).value
    5
    commonAncestor(node1,node4,node5).value
    3
    """
    if head==None: return
    if (node1.value<=head.value)&(node2.value>=head.value):
            return head
    if (node1.value<=head.value)&(node2.value<=head.value):
            return commonAncestor(node1,node2,head.left)
    if (node1.value>=head.value)&(node2.value>=head.value):
            return commonAncestor(node1,node2,head.right)

class Node:
    def __init__(self,value,left=None,right=None):
        self.value=value;self.left=left;self.right=right

if __name__ == "__main__":
    import doctest
    doctest.testmod()