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}

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 - Quants and Plodders

June 14, 2008 – 6:51 pm

I discussed in my previous post that many problems can be solved in two ways - the Quant way and the Plodders way. Here’s a good example.

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'

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'

Here’s the punch line: given that, let’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”. What’s the quickest way to do this?
Answer

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

Something very basic - I’m reading some finance books and needed a refresher:

There is a “mathematical constant” e such that the function e^x has the same value as its tangent line (derivative) for every value of x.

The natural logarithm of x is the number to which e has to be raised to equal x.
e^1 = e The natural log of e is 1.
e^0 = 1 The natural log of 1 is 0.

Another critical property for finance of 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 n<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()

Binary Search - Python

June 1, 2008 – 1:12 am

Further to my previous post, a simple binary search O(log n) algorithm:

def binarySearch(node,value):
    """
    >>> node1=Node(1)
    >>> node4=Node(4)
    >>> node3=Node(3,node1,node4)
    >>> node7=Node(7)
    >>> node5=Node(5,node3,node7)
    >>> binarySearch(node5,4)
    5 3 4
    >>> binarySearch(node5,5)
    5
    """
    print node.value,
    if value==node.value: return
    if value<node.value:
        binarySearch(node.left,value)
    else:
        binarySearch(node.right,value)
    return None

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()

Tree Traversal - Python

May 31, 2008 – 7:48 pm

Another question posed in the Programming Interviews Exposed book. A pre-ordered traversal of a binary tree (counterclockwise starting at root, printing nodes as you encounter them) is pretty straight forward, and a very natural thing to implement with recursion:

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

>>> node1=Node(1)
>>> node2=Node(2)
>>> node3=Node(3,node1,node2)
>>> node4=Node(4)
>>> node5=Node(5,node3,node4)

>>> def traverse(node):
	if node==None: return
	print node.value
	traverse(node.left)
	traverse(node.right)

>>> traverse(node5)
5
3
1
2
4
>>>

The trick is how to implement this without recursion - thinking caps on! Well, using a stack may be the best way (see earlier post), though it’s amazing how much more convoluted it gets. I’m sure it can be done more efficiently, though I like my algorithm better than the one in the book. Anyone have something better?

def treeWalker(node):
    """
    >>> node1=Node(1)
    >>> node2=Node(2)
    >>> node3=Node(3,node1,node2)
    >>> node4=Node(4)
    >>> node5=Node(5,node3,node4)
    >>> treeWalker(node5)
    5
    3
    1
    2
    4
    >>>
    """
    lifo=Lifo()
    while True:
        print node.value
        if node.left!=None:
            lifo.push(node)
            node=node.left
        else:
            node=lifo.pop()
            if node==None: return
            node=node.right

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

class Lifo:
    def __init__(self):
        self.lifo = ()
    def push(self, data):
        self.lifo = (data, self.lifo)
    def pop(self):
        if len(self.lifo)==0: return None
        ret, self.lifo = self.lifo
        return ret

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

Fibonacci - Python

May 31, 2008 – 2:18 am

Ok so if you’re interviewing for a programming job you have to be able to whip out a quick Fibonacci sequence at the drop of a hat, even if inelegant. This prints the fib series for n terms:

>>> def fib(n):
	a,b=0,1
	for i in range(n):
		print a,
		a,b=b,b+a

>>> fib(10)
0 1 1 2 3 5 8 13 21 34
>>>
>>>

There’s a recursive approach as well:

>>> def fib(n,a=0,b=1,counter=0):
	print a,
	if counter<(n-1): fib(n,b,a+b,counter+1)

>>> fib(10)
0 1 1 2 3 5 8 13 21 34
>>>

Python has a nice concept called iterators which can be used as well. Basically you implement an __iter__ method, and then code a next method, and then you can use your class in a for loop.

>>> class fib():
	def __init__(self):
		self.a,self.b=0,1
	def __iter__(self):
		return self
	def next(self):
		ret=self.a
		self.a,self.b=self.b,self.a+self.b
		return ret

>>> for i in fib():
	print i,
	if i>10: break

0 1 1 2 3 5 8 13
>>>

You can get the benefit of an iterator in Python without the __iter__ and next methods - you just have to invoke yield somewhere in your function and you have a Generator - which will generate an iterator.

>>> def fib(a=0,b=1):
	while True:
		yield a
		a,b=b,a+b

>>> fib=fib()
>>> for i in range(10): print fib.next(),

0 1 1 2 3 5 8 13 21 34
>>>

Here’s some recursion on steroids, generating the nth fib term (though starting at 1). Somewhat of a brainstretcher to think through what’s going on in this recursion though. And I think something like O(2^n) time.

>>> def fib(n):
	    if n<=1: return n
	    return fib(n-1)+fib(n-2)

>>> fib(10)
55

Anybody have another favorite fib implementation?

More Linked Lists - Acyclic or not?

May 30, 2008 – 4:27 am

Another problem in the Programming Interviews Exposed book (see previous post) is to determine whether a Linked List is Acyclic or not.

The most obvious way to do this is to iterate over the list, checking whether the next element is one that you’ve seen before. So as you get to an element, you sweep back from head to current.

def isAcyclic1(head):
    """
    >>> e1=Element(1)
    >>> e2=Element(2)
    >>> e3=Element(3)
    >>> e4=Element(4)
    >>> e5=Element(5)
    >>> e1.next=e2
    >>> e2.next=e3
    >>> e3.next=e4
    >>> e4.next=e5
    >>> isAcyclic1(e1)
    True
    >>> e5.next=e3
    >>> isAcyclic1(e1)
    False
    >>> e5.next=e4
    >>> isAcyclic1(e1)
    False
    >>> e5.next=e2
    >>> isAcyclic1(e1)
    False
    """
    curr=head
    while curr!=None:
        sweeper=head
        while sweeper!=curr:
            if curr.next==sweeper:
                return False
            sweeper=sweeper.next
        curr=curr.next
    return True

This is an O(n squared) solution. There’s a better way, of course, and here I’ll admit I needed a hint from the book. As soon as I saw something about fast and slow pointers it clicked - it’s quite a clever solution. You start a fast pointer, skipping elements, which if acyclic will get to the end quickly. If cyclic, it will eventually trip over the slow pointer. It turns out to be an O(n) solution. Smart.

def isAcyclic2(head):
    """
    >>> e1=Element(1)
    >>> e2=Element(2)
    >>> e3=Element(3)
    >>> e4=Element(4)
    >>> e5=Element(5)
    >>> e1.next=e2
    >>> e2.next=e3
    >>> e3.next=e4
    >>> e4.next=e5
    >>> isAcyclic2(e1)
    True
    >>> e5.next=e3
    >>> isAcyclic2(e1)
    False
    >>> e5.next=e4
    >>> isAcyclic2(e1)
    False
    >>> e5.next=e2
    >>> isAcyclic2(e1)
    False
    """
    slow=head
    fast=head.next
    while fast!=None:
        if fast.next==None:
            return True
        if (fast==slow)|(fast.next==slow):
            return False
        fast=fast.next.next
        slow=slow.next
    return  True

More on Linked Lists - flattening and unflattening

May 30, 2008 – 3:04 am

More from the Programming Interviews Exposed book (see last post). In this problem you take a double linked list (where each node knows its previous and next nodes) with child elements, and flatten it. Then unflatten it back to its original structure. It took me a few minutes to get the AHA moment around using recursion for unflattening.

class Node:
    def __init__(self,data,prev=None,next=None,child=None):
        self.data=data
        self.prev=prev
        self.next=next
        self.child=child

class ListFlattener:
    """
    >>> node1=Node(1)
    >>> node5=Node(5)
    >>> node1.child=node5
    >>> node2=Node(2)
    >>> node3=Node(3,node1,None,node2)
    >>> node1.next=node3
    >>> node4=Node(4,node2)
    >>> node2.next=node4
    >>> ListFlattener.listAsArray(node1)
    [1, 3]
    >>> ListFlattener.flattenList(node1)
    >>> ListFlattener.listAsArray(node1)
    [1, 3, 5, 2, 4]
    >>> ListFlattener.unflattenList(node1)
    >>> ListFlattener.listAsArray(node1)
    [1, 3]
    >>> ListFlattener.flattenList(node1)
    >>> ListFlattener.listAsArray(node1)
    [1, 3, 5, 2, 4]
    >>> ListFlattener.listAsArray(ListFlattener.findTail(node1),False)
    [4, 2, 5, 3, 1]
    """
    @staticmethod
    def flattenList(head):
        curr=head
        tail=ListFlattener.findTail(head)
        while curr!=None:
            if curr.child!=None:
                tail=ListFlattener.appendChildToEnd(curr,curr.child,tail)
            curr=curr.next

    @staticmethod
    def unflattenList(head):
        curr=head
        while curr!=None:
            if curr.child!=None:
                curr.child.prev.next=None
                curr.child.prev=None
                ListFlattener.unflattenList(curr.child)
            curr=curr.next

    @staticmethod
    def appendChildToEnd(node,child,tail):
        tail.next=child
        child.prev=tail
        return ListFlattener.findTail(child)

    @staticmethod
    def findTail(node):
        while node.next!=None:
            node=node.next
        return node

    @staticmethod
    def listAsArray(node,forward=True):
        list=[]
        while node!=None:
            list.append(node.data)
            if forward:
                node=node.next
            else:
                node=node.prev
        return list

Linked List Interview questions…

May 29, 2008 – 4:10 am

I hadn’t done much programming for a while so I thought I’d brush up on some basic stuff. I bought Programming Interviews Exposed.

I did some of the Linked List stuff in the first section in Python. The code came out pretty close to the solutions in the book, though that was mainly in C++. I did like the problem of finding the Mth to last and needing to keep the lagging pointer - once you know it the answer is obvious, but it took a few minutes before it dawned on me.

class Stack:
    """
    Adapted from Programming Interviews Exposed problems
    LinkedList implementation that keeps track of head and tail

    Basic tests - push,pop,remove
    >>> s=Stack()
    >>> s.push(1)
    >>> s.push(2)
    >>> s.push(3)
    >>> s.push(4)
    >>> s.pop()
    4
    >>> e=s.head.next
    >>> s.remove(e)
    True
    >>> s.head.data
    3
    >>> s.tail.data
    1
    >>> e=s.head.next
    >>> s.remove(e)
    True
    >>> s.head.data
    3
    >>> s.tail.data
    3
    >>> e=s.head
    >>> s.remove(e)
    True
    >>> s.head
    >>> s.tail
    """

    def __init__(self):
        self.head=None
        self.tail=None

    def push(self,data):
        if self.head==None:
            self.head=Element(data,None)
            self.tail=self.head
        else:
            self.head=Element(data,self.head)

    def pop(self):
        oldhead=self.head
        if oldhead==None:
            return None
        self.head=oldhead.next
        if self.head==None:
            self.tail=None
        return oldhead.data

    def remove(self,element):
        if self.head==None:
            return False
        if self.head==element:
            self.head=self.head.next
            if self.head==None:
                self.tail=None
            return True
        curr=self.head
        while curr!=None:
            if curr.next==element:
                curr.next=curr.next.next
                if curr.next==None:
                    self.tail=curr
                return True
            else:
                curr=curr.next
        return False

    def insertAfter(self,element,data):
        """
        >>> s=Stack()
        >>> s.insertAfter(None,1)
        True
        >>> s.head.data
        1
        >>> s.tail.data
        1
        >>> s.insertAfter(None,2)
        True
        >>> s.head.data
        2
        >>> s.tail.data
        1
        >>> e=s.head
        >>> s.insertAfter(e,3)
        True
        >>> s.head.data
        2
        >>> s.tail.data
        1
        >>> s.head.next.data
        3
        >>> e=s.tail
        >>> s.insertAfter(e,4)
        True
        >>> s.head.data
        2
        >>> s.tail.data
        4
        """
        if (element==None)|(self.head==None):
            self.head=Element(data,self.head)
            if self.head.next==None:
                self.tail=self.head
            return True
        curr=self.head
        while curr!=None:
            if curr==element:
                curr.next=Element(data,curr.next)
                if curr.next.next==None:
                    self.tail=curr.next
                return True
            curr=curr.next
        return False

    def removeHead(self):
        """
        >>> s=Stack()
        >>> s.removeHead()
        >>> s.head
        >>> s.tail
        >>> s.push(1)
        >>> s.removeHead()
        >>> s.head
        >>> s.tail
        >>> s.push(1)
        >>> s.push(2)
        >>> s.removeHead()
        >>> s.head.data
        1
        >>> s.tail.data
        1
        """
        if self.head!=None:
            self.head=self.head.next
            if self.head==None:
                self.tail=None

    def findMToLastElement(self,m):
        """
        >>> s=Stack()
        >>> s.push(1)
        >>> s.push(2)
        >>> s.push(3)
        >>> s.findMToLastElement(1).data
        1
        >>> s.findMToLastElement(2).data
        2
        >>> s.findMToLastElement(3).data
        3
        >>> s.findMToLastElement(4)
        """
        mToLast=None
        curr=self.head
        count=0
        while curr!=None:
            count+=1
            if count==m:
                mToLast=self.head
            if count>m:
                mToLast=mToLast.next
                if mToLast==None:
                    return None
            curr=curr.next
        return mToLast

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

Python - gotta love it

May 27, 2008 – 2:39 am

I’ve programmed in lots of languages (have on past occasion considered myself a Smalltalk, Java, Ruby… aficionado.) But I really like Python and the mindset of the community - a smart, no-nonsense efficiency. Something simple like unit testing - you can do it by having Python execute your docstrings, which you can cut and past straight from the shell. Nice!

<pre name="code" class="python:showcolumns">
def largestArrayCompareToMax(array):
    """
    Prints largest value in array by comparing to max - O(n) solution
    >>> largestArrayCompareToMax([1,5,9,2,4,6,8,3,7])
    9
    """
    max = array[0]
    for i in range(len(array)):
        if array[i] > max:
            max = array[i]
    print max

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

Python LIFO implementation

May 27, 2008 – 2:13 am

I like this Python LIFO implementation - it’s very Pythonesque, using tuples (which are insanely fast to unpack, apparently.) I implemented a Lifo myself using some weird array thing which, after seeing this, I won’t post here…

class Lifo:
    """
    From http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68436
    >>> lifo=Lifo()
    >>> lifo.append(1)
    >>> lifo.append(2)
    >>> print lifo.pop()
    2
    >>> print lifo.pop()
    1
    >>> print lifo.pop()
    Traceback (most recent call last):
        ...
    ValueError: need more than 0 values to unpack
    """
    def __init__(self):
        self.lifo = ()
    def append(self, data):
        self.lifo = (data, self.lifo)
    def pop(self):
        # Use tuple unpacking - popping an empty Lifo will
        # raise a ValueError, which is OK
        ret, self.lifo = self.lifo
        return ret

Weighing oranges

May 18, 2008 – 4:39 am

The puzzle

You have 8 oranges - one is heavier than the others. How many weighings on a justice scale do you need to determine which one it is?

Answer

It’s tempting to split the oranges in the middle, and weigh 4 and 4, which would take 3 weighings. But you can do it in two weighings. Take 3 and 3 and weigh these. If equal, you know it’s in the two remaining and you can see which it is with another weighing. If not, take the heavier bunch and weigh 2 of the oranges - one will either be heavier, or if equal you know it’s the one remaining.

Two weighings will also work for nine oranges (it’s normally asked with eight as it makes it more tempting to split them evenly). Three weighings can get you to 27, which is 3 to the power of 3 - so you see the pattern.

Another variant of this puzzle is that you have 12 oranges with one being a different weight, but don’t know whether it’s heavier or lighter. This requires more weighings - and is a bit tricker.

The first step is to group the oranges in three groups - let’s call them group A, B and C - with 4 oranges each. Then within each group, you divide the oranges into a single orange (let’s call it A1 for the A group) and a group of 3 oranges (let’s call this A3 for the A group).

Before we start, let’s remember from the first part of the puzzle that if you have 3 oranges and you know if one is heavier or lighter, then you can find it in one weighing. We’ll call this the “known 3 orange case” in the text below.

First weighing:
A1, A3 <--> B1, B3 (leaving out C1 and C3)

Let’s take the case where they balance. You know the orange is in C1 or C3. You can then weigh:
C3 <--> A3
If they balance it’s C1. If they don’t you can go into a third weighing of C3 with a “known three orange case”.

If the first weighing doesn’t balance (let’s assume that A1, A3 are heavier), then of course you know it’s not in C1 or C3 and you go into a second weighing as follows:

Second weighing:
A1, B3 <--> B1, C3 (leaving out A3)

If they balance then we go into a third weighing on A3 with a “known three orange case” (we know A3 has the heavy orange from the first weighing).

If A1, B3 is heavier, then you know that either A1 is heavier or B1 is lighter (it can’t be in B3 as we said that was in the lighter side in weighing one) - and you can find out which one by comparing one of them against C1.

If B1, C3 is heavier then you go into a “known three orange case” with B3 knowing that it contains a lighter orange (it can’t be A1 or B1 as they were on the contradictory side of the scale on the first weighing).

Note: We assumed A1, A3 heavier after the first weighing - if it was B1, B3 you just do the above replacing A groups for B groups.

So there you have it - tricky to follow but you can do the 12 orange case where you don’t know if the one orange is heavier or lighter in 3 weighings.