Pascal's Triangle

Pascal's Triangle is a shortcut for getting coefficients most often used binomial probability. The root element is 1. Every other element is the sum of the one or two above it (diagonally left and diagonally right).

There are several variations of the problem:

Print out the triangle to a specific row;

Return a given row of the triangle;

Return a given element (by row and index) of the triangle.

All of them use the same basic logic. You explain this to the interviewee and ask them to solve it on paper or on a whiteboard.

Recursive Solution

The simplest version is a recursive solution, something like:

01.#!/usr/bin/python

02.defvalue(row, index):

03.ifindex < 0orindex > row:

04.return0

05.ifindex ==0orindex ==row:

06.return1

07.returnvalue(row-1, index-1) +value(row-1, index)

08.

09.defrow(n):

10.return[value(n, x) forx inxrange(0, n+1)]

11.

12.fori inxrange(10):

13.printrow(i)

If a candidate can produce this it is at least a working solution
even though the performance (for non-trivial n) is prohibitive. Ideally
they would be able to point this out (plus the exponential big-O
performance).

On my Macbook Pro (2010) this runs for n=20 in about 0.8 seconds.

Memoization

Some candidates will improve this solution by identifying and caching the repeated calculations. Something like this:

01.importcollections

02.

03.values =collections.defaultdict(dict)

04.

05.defvalue(row, index):

06.result =values[row].get(index)

07.ifresult isnotNone:

08.returnresult

09.ifindex < 0orindex > row:

10.return0

11.ifindex ==0orindex ==row:

12.return1

13.result =value(row-1, index-1) +value(row-1, index)

14.values[row][index] =result

15.returnresult

Real time for n=20 is 0.03 seconds. Bonus points if the candidate
correctly states this as "memorization" (rather than the more generic
"caching").

Iterative Solution

A more common optimization is to use an iterative rather than
recursive solution. The simplest version of this is something like:

01.#!/usr/bin/python

02.rows =[[1]]

03.

04.forrow inxrange(1, 20):

05.values =[1]

06.prev =rows[-1]

07.forindex inxrange(1, row):

08.values.append(prev[index-1] +prev[index])

09.values.append(1)

10.rows.append(values)

11.

12.forrow inrows:

13.printrow

Performance is similar to the previous one (0.028 seconds). There are lots of subtle variations of this.

Dynamic Programming

The astute candidate will realize that you don't need to store the
rows at all. You only ever need the current and the previous rows. This
reduces space for O(n2) to O(n).

01.#!/usr/bin/python

02.prev =[]

03.forrow inxrange(20):

04.curr =[1]

05.forindex inxrange(1, row):

06.curr.append(prev[index-1] +prev[index])

07.curr.append(1)

08.printcurr

09.prev =curr

0.027 seconds.

Bonus Points

Assuming f(r, i) returns the value for row r and index i, a candidate
may well point out that the triangle is symmetrical, specifically that
f(r, i) == f(r, r-i), meaning you, at most, only have to calculate half
of the triangle. This is particularly relevant if they are asked to
return a specific value (ie f(117, 116) == f(117, 1) == 117).

The second optimization one could make is that since f(r, i) == f(r,
i-1) + f(r, i) then to calculate f(r, i) you only need to calculate up
to the i'th element of each row.

Why is this a good question?

As demonstrated, the code solutions are short. They're longer in,
say, C, C++ or Java rather than Python but not that much longer. The
point here isn't to get a perfect solution from the interviewee (meaning
that deducting points for a missing colon or a typo would be silly).
The purpose of the exercise is to demonstrate the they can turn a
relatively simple algorithm into code. They have the thought process to
do so. In doing so, their familiarity with their chosen language should
be obvious.

Also, there are several degrees of solutions. Any solution trumps no
solution but the quality of the solution will give you a useful signal
(IMHO).

What should a coding test tell you?

A coding test like this is a negative filter. Assuming your chosen
problem is sufficiently simple, if an interviewee can't turn it into at
least the outline of code in a reasonable length of time then that's a
red flag. If they can do it in record time it doesn't mean they're a
rock star. You're just trying to weed out candidates who should've
already been screened out.

What's a reasonable length of time? IMHO 5 minutes or less is
fast (arguably blazing fast). Anything under 10 minutes is fine. If
someone is taking more than say 15-20 minutes, that is possibly cause
for concern.

Conclusion

The key qualities in a coding test are:

It needs to be relatively simple. If it takes more than about 20-30 lines of Python to solve it's probably too complex;

It needs to be easy to explain. If someone doesn't know what Pascal's Triangle is, that's not a problem. Explain it; and

The goal is to put thought into code. That code doesn't need to be perfect. It just needs to be sufficiently expressive.