I am releasing early versions of each data structure on Github for testing and API feedback. Here is the post on LinkedIn that provides permanent links to the repo for each data structure.

https://www.linkedin.com/pulse/typescript-math-toolkit-data-structures-jim-armstrong

Recent additions since last post include Binary Heap and Graph classes.

Enjoy!

]]>https://github.com/theAlgorithmist/TSBinaryTreeLibrary

Enjoy … and drink lots of coffee

]]>Another item in the request department was a flyout panel. Now, I don’t care for animation for the sake of animation, but I do concede that some (albeit limited) valid use cases exist for such a UI element.

Finally, I wanted to take the Angular2 CLI for one final ride before production release and the update to Angular 4 later this week. So, it’s time for another example

Since the topic of the first request is a 2D table (which would be better implemented with a 3rd party datagrid in a larger application), I decided to do some spreadsheet-style analytics on a dataset that was made popular in the book ‘Machine Learning in R’ by Lantz. This is accomplished with the Typescript Math Toolkit and the analytic results are displayed in a flyout panel.

I also wanted to add one more item to the ‘how to’ part of the application, namely custom attribute Directives. This application illustrates the use of a ‘make clickable’ Directive. This custom attribute Directive allows a simple attribute to be used to transform a DOM element such as a paragraph or H1 tag into a clickable element, i.e.

<h1 makeClickable (onClick)=”__onShowClicked()” [innerHTML]=”summaryString”></h1>

Now, this could be accomplished with an anchor or injecting custom script inside the Component’s code-behind. The use of an attribute Directive allows existing markup and styling to remain largely unaltered and the intent is clearly displayed in a template as opposed to code (which takes time for another developer to deconstruct). The Directive is also highly reusable.

The application reads data from a PHP file that is provided with the code distribution. It is necessary to move this file to a server and alter one line of code in the model in order to build and run the application. A CORS header is provided that allows the application to be served locally through the Angular 2 CLI.

The opening screen is rather basic:

Click on the “> Show Summary Statistics” text to display the flyout panel with summary statistics obtained from the Typescript Math Toolkit. Ah, a nice mix of code and math. Just what I like

Click on “> Hide Summary Statistics” to close the flyout panel and restore the original display.

Then, deconstruct the code and have fun. On the subject of code, you probably want to know here to get it, so point your friendly neighborhood browser to this Github repo.

Enjoy!

Although I wanted to be in line with the A2/Leaflet starter, I also wanted to go in a completely different direction, so a separate project seemed like the best approach. My goals for this project include:

- Use the Angular2 CLI as the build tool
- Create a complete micro-application as the demonstration environment
- Adhere to concepts from Flux and Redux w/o 3rd party software
- Classes adhere to principles such as single responsibility
- Provide progress and error indication for services
- Illustrate production-quality features such as preventing side effects from repeatedly clicking the same button
- Provide an example of working with the component change detector
- Use the Typescript Math Toolkit Location class for location data
- Only minimal understanding of Leaflet is required

Although a simple ‘loading’ component is provided with the code distribution, tile loading is sufficiently fast that it is unlikely to be seen. After building and running the project, the application appears as shown below.

The map is initially centered on Carrollton, TX where I currently live.

Enter an address (which could be as simple as ‘Austin, TX’) or click ‘Show Current Location’ to move the map based on current IP address. Third-party services are used to geocode either the IP or physical address and progress indications are provided in the navigator component. A result of moving to Austin, TX is shown below.

The Typescript Math Toolkit Location class is used for location data and service errors are seamlessly reported to the user.

Very little Leaflet knowledge is required to deconstruct and expand upon the code. If you have gone through the Leaflet ‘Getting Started’ guide, then you know enough about that package to deconstruct the code.

And, speaking of code, I know you want it so point your friendly neighborhood browser to the Github repository here and have fun!

]]>*Problem: You are given an array, A, of numbers of length N. You are also given a function, F, that accepts a single number as an argument and it returns a boolean. The function body is not relevant; it returns true if a certain condition is met and false otherwise. It is known that if the function returns true for A[j], j = 0, 1, … N-1, then it returns true for j+1, … N-1. Suggest a strategy that identifies the smallest index, j, such that F( A[j] ) is true with no more than two calls to F where the function returns true. F may return false as many times as needed for the algorithm to work. Return -1 if no such index exists. The strategy for this problem should be designed to minimize the worst-case complexity. Your presentation should include at least detailed pseudocode for your suggested algorithm (bonus points for actual code and specs).*

Although the stated problem may sound highly artificial, I did work on an application some time ago in which a complex true/false test was involved. In some cases, a couple conditions could be tested and false could be quickly proven. Proving true or false was much more computationally intense in absence of those conditions. We ended up strategically re-ordering the data so that it was possible to eliminate large chunks of data from the analysis. So, the problem may be less outlandish that it appears on first reading.

The person submitting the problem came to the conclusion that the ‘two true returns’ requirement be relaxed to three and use binary search to identify a smaller interval, followed by a linear search to locate the exact index.

It is natural for a good programmer to think of binary search when scanning an array for a condition in which an order relationship is known to hold in advance. In terms of worst case for the stated problem, it will not generally be possible to locate the required index and make no more than two calls to F where the return is true.

For purposes of the discussion, array elements are referred to as first, second, … Nth in terms of one-based indices, so a_{j} refers to the jth element, j = 1, 2, … N. The function is referenced in lowercase, i.e. f().

A simple implementation of a linear search is as follows:

1 – Test a_{N}. If f returns false, then return -1

2 – Otherwise, start at a_{1} and test each element in sequence through N-1. If f returns true for any index, return either that index or -1 if all array elements test false.

In terms of worst-case complexity, the worst case is when f(a_{N-1}) is true. Although only one true return is required, all N array elements are tested.

The linear search may be improved by using a constant step size, k. In this case, the array is broken into intervals and a ‘forward sweep’ is performed by skipping over k elements each test. The goal is to find any array element in which the test is true by ‘leaping’ over many in which it is false. Once a true test is discovered, the previous k-1 array elements must be tested in sequence to isolate the first index for which the test is true.

This approach is guaranteed to have no more than two true results and it will always locate the required index. The worst case for this algorithm occurs when the minimum array index is next to last. Let’s temporarily presume that k is chosen to divide N evenly so that the chosen step size produces exactly N/k = Nk^{-1} intervals. The expected number of function evaluations, e(k), is given by

e(k) = Nk^{-1} + k – 1

Although this is a problem in discrete math, we can use a continuous model to obtain some insight into the best choice for k. A necessary condition for a minmimum of e is that the first derivative is zero,

e'(k) = -Nk^{-2} + 1 = 0 => k^{-2} = N^{-1}

or k = sqrt(N).

The second derivative, e”(k), is 2Nk^{-3} which is everywhere positive for k > 0, which indicates that the extreme point is a minimum. Now, it may be that sqrt(N) is not exactly integral; take N = 50, for example. sqrt(50) ~ 7.07, so we might surmise that k = 7 is a good choice, although this leaves an interval of width 1 at the end. The ones-based array elements tested are 7, 14, 21, 28, 35, 42, 49, 50 (there are actually 8 intervals). The worst case occurs at array element 48. This requires testing 7 (F), 14 (F), 21 (F), 28 (F), 35 (F), 42 (F), 49 (T), 43 (F), 44 (F), 45 (F), 46 (F), 47 (F), 48 (T), or a total of 13 tests.

Note that we could have taken the ceiling of sqrt(N) in this case and achieved the same result. With k = 8, the worst-case scenario is the first true test at the 47-th element. Tests are 8 (F), 16 (F), 24 (F), 32 (F), 40 (F), 48 (T), 41 (F), 42 (F), 43 (F), 44 (F), 45 (F), 46 (F), 47 (T), for a total of 13.

Although this heuristic provides a ‘good’ value for the constant step-size model, nothing has been shown to indicate that this is the best possible model out of all possible models for this problem. Consider, for example, the following variable step-size model,

k_{i} = k_{i-1} + d

where d is a non-zero integer. In this case, a starting value of k is chosen and then subsequent step sizes become larger or smaller by a fixed amount. For d > 0, the first interval is of width k, the second is of width k+d, the third is of width k+2d, etc. This trades jumping through large parts of the array that hopefully return false for an increasing linear search interval. The latter tradeoff is the problem with such a model in terms of worst-case scenario. Consider an example with N = 50, k = 8, and d = 1. Initial elements tested are 8, 17, 27, 38, 50. The worst-case scenario is when the first true result occurs at the 49th element. This requires 5 tests to locate the interval, followed by testing elements 39 through 49 in sequence for a total of 16 tests. The situation does not improve by increasing the initial value. Take 10, for example. Initial elements tested are 10, 21, 33, 46, 50. Worst case scenario is at element 45 for a total of 4 + 13 or 17 tests.

While not a conclusive proof, these counter-examples illustrate the problem with positive step-size increases, even with the smallest-possible value of d = 1. The problem is only exacerbated with larger values of d, so let’s discard that part of the model and consider negative values of d. Again, we begin with the smallest-magnitude value, d = -1, which yields intervals of widths k, k-1, k-2, k-3, …

Suppose that k is chosen so that there are exactly m intervals (and this may not always be true in the general case).

In that instance,

k + (k-1) + (k-2) + (k-3) + … + (k-m-1) = N

mk – (1 + 2 + … + (m-1)) = N

The second term on the left-hand side is the sum of the first m-1 integers which is (m-1)m/2 , so

mk – ((m-1)m)/2 = N or mk – m^{2} + m = 2N

This yields a quadratic equation just to isolate the number of intervals and that is only in the ideal case. Analyzing the optimal choice for initial k with a continuous model is a rabbit hole for which we do not wish to discover the depth

There is some potential value with this model as we could start with a larger choice of k than sqrt(N). Since the interval width decreases by one each step, each successive ‘forward’ step is balanced by a corresponding reduction in the number of sequential tests required in that interval. The ideal starting value of k, however, is still an open question.

In many cases such as this, we can gain some insight by a analyzing a good choice for successive values of N and see if a pattern emerges. If such a heuristic holds for expected values of N, then we have a reasonable starting point for the problem that is commensurate with a proper timebox for this type of analysis. Remember that the goal is to investigate a problem and prepare a report, not write a paper for a referred journal. Demonstrating how you timebox and apply yourself to such an analysis is likely to be an important part of the interview process.

For N = 1, k = 1. For N = 2 and 3, k = 2. The following sequence uses a value of k that is optimal based on explicit enumeration. The interval width is decreased by one until it is not possible to decrease any further without exceeding N or the interval width is reduced to one. There are as many of these singleton intervals as needed to reach the end of the array.

e^{*} is the expected number of worst-case function evaluations to solve the problem.

N = 4

k = 2

intervals: 2, 1, 1

e^{*} = 3

—–

N = 4

k = 3

intervals: 3, 1

e^{*} = 3

N = 5

k = 3

intervals: 3, 2

e^{*} = 3

N = 6

k = 3

intervals: 3, 2, 1

e^{*} = 3

—–

N = 7

k = 4

intervals: 4, 3

e^{*} = 4

N = 8

k = 4

intervals: 4, 3, 1

e^{*} = 4

N = 9

k = 4

intervals: 4, 3, 2

e^{*} = 4

N = 10

k = 4

intervals: 4, 3, 2,1

e^{*} = 4

—–

N = 11

k = 5

intervals: 5, 4, 2

e^{*} = 5

N = 12

k = 5

intervals: 5, 4, 3

e^{*} = 5

.

.

.

N = 20

k = 6

intervals: 6, 5, 4, 3, 2

e^{*} = 6

.

.

.

N = 50

k = 10

intervals: 10, 9, 8, 7, 6, 5, 4, 1

e^{*} = 10

The noticeable pattern from these enumerations is that k is to be chosen such that the sum of the first k integers is greater than or equal to N. This value also happens to be the number of worst-case evaluations to locate the required index.

No proof is supplied; the analysis is completely heuristic. In any event,

k(k+1)/2 ≥ N

k^{2} + k ≥ 2N or k^{2} + k – 2N ≥ 0 [1]

If N = 100, for example, k = 14, which yields e^{*} = 14. This is better than e^{*} = 19, which is the best result from a constant step size. In general, one step of refinement of a direct solution may be required to satisfy the inequality since k is constrained to be integral.

The next consideration is a variable step size model. Choose some initial interval width, k_{0}. The i-th interval width is given by k_{i} = k_{i-1} + d_{i}, where d_{i} is a nonero integer. You should have observed by now that the worst-case complexity associated with each interval is the number of steps to get to the interval endpoint plus the interval width minus one. Based on this observation, k_{0} should be less than that indicated by eq. [1]. No subsequent interval width could equal the optimal value of k from [1], otherwise the worst-case complexity would be no better than the (constant) decreasing interval model. With this restriction on k_{0}, the number of steps to reach the final interval increases, which means that it is likely that no variable step size could improve upon the minimal worst-case complexity from the constant decreasing step-size model. This is an intuitive argument – not a prooof – which is suitable for an initial presentation on a topic such as this one.

The conclusion of this brief analysis is that the constant, decreasing step-size model is the best one to apply for the task of minimizing worst-case complexity for the stated problem. The bonus code is available from the TS Programming Test Problems Github repo.

I sure hope the bonus is a Starbucks gift card

]]>I enjoyed having access to Templates in C++ (now called Generics in C# and Typescript). The availability of Generics in Typescript allows the creation of a single class that accommodates multiple data types. The specific implementation of the Priority Queue also illustrates some more advanced features of Typescript, so I thought it would be worthy of a more detailed blog post.

The TSMT Priority Queue is based on my past usage of a priority queue over the years. It consists of an array of prioritizable items, each of which has three properties, a *priority*, a *timestamp*, and a *data* reference. If we allow the data to be of arbitrary type, the contract may be specified in a simple interface.

export interface IPrioritizable<T> { priority: Number; // priority, integer>= 0 timestamp: Number; // optional timestamp, expected to be an integer >= 0 data: T; // arbitrary, but constructable data type such as Object or a Class }

A prioritizable item implements this interface. In my past usage, data associated with the prioritizable item was an Object or class, such as

class PItem { protected _name: string = "name"; protected _id: number = 0; protected _value: number = 0; constructor() {} // accessors/mutators removed to save space public computeValue(someData: Object): void { // compute value from supplied data } }

I would construct the data along with the item and set the data reference in the prioritizable item. A discussion with a couple of developers interested in using this Priority Queue yielded a different use case. They wanted the option of constructing the data type when the prioritizable item was constructed. They would access and set the data at a later point in the application.

While not the way I would approach the problem, it was a use case I wanted to at least try to support in the alpha release. This led to the following implementation of the Prioritizable class.

export class Prioritizable<T> implements IPrioritizable<T> { protected _priority: number; protected _timestamp: number; protected _data: T; /** * Construct a new Prioritizable item * * @param TConstructor : { new (): T } (optional) Reference to a constructable object * * @return Nothing Constructs the supplied data type (if provided) and sets the internal data reference. Priority and timestamp are initialized to zero. */ constructor( TConstructor?: { new (): T } ) { this._priority = 0; this._timestamp = 0; // pre-construct the data type? if (TConstructor) this._data = new TConstructor(); } /** * Access the priority * * @return number Current priority value */ public get priority(): number { return this._priority; } /** * Assign the priority * * @param value: number Priority value (must be greater than or equal to zero) - expected to be integer, but this is not currently enforced * * @return Nothing Assigns the priority if the input is a valid number */ public set priority(value: number) { if (!isNaN(value) && value === value && value >= 0) this._priority = value; } /** * Access the timestamp value * * @return number Current timestamp value */ public get timestamp(): number { return this._timestamp; } /** * Assign the timestamp value * * @param value: number Timestamp value (must be greater than or equal to zero) - expected to be integer, but this is not currently enforced * * @return Nothing Assigns the timestamp if the input is a valid number */ public set timestamp(value: number) { if (!isNaN(value) && value === value && value >= 0) this._timestamp = value; } /** * Access the data item * * @return T Direct reference to the data item; the data is not currently required to be cloneable, so a direct reference is provided. Use this method with caution. */ public get data(): T { return this._data; } /** * Assign the data item * * @param value: T Reference to a data value of type T * * @return Nothing Directly assigns the supplied reference to the internal data value. Use caution to not make further modifications to the supplied value. */ public set data(value: T) { if (value) this._data = value; } }

The constructor is rather unusual and requires an optional constructable object to be passed. For example,

*let __pObject: Prioritizable<Object> = new Prioritizable<Object>(Object);*

(creates new prioritizable item with *Object* data, constructs a new *Object*, and sets the internal data reference)

*let __pObject: Prioritizable<Object> = new Prioritizable<Object>();*

(creates new prioritizable item with *Object* data; internal data reference is null and must be set later using mutator)

This implementation allows both use cases to be implemented, but is currently experimental.

Suppose a class, *PItem*, is available that represents the data to be associated with a prioritizable item. My preferred use case to add items to the queue is:

let queue: TSMT$PriorityQueue<PItem> = new TSMT$PriorityQueue<PItem>(); let item1: Prioritizable<PItem> = new Prioritizable<PItem>(); let pItem1: PItem = new PItem(); item1.priority = 1; item1.timestamp = 1001; item1.data = pItem1; . . . queue.addItem(item1);

The TSMT Priority Queue uses priority as a default, primary sort key. A timestamp value (typically another integer greater than or equal to zero) may be used as a secondary key. A type alias is defined with the priority queue,

export type SortType = 'priority' | 'timestamp';

Sort criteria are specified by a mutator that accepts an array of *SortType* values. A type guard is also used to ensure validity of each individual item in the mutator. A type guard is a runtime check to ensure validity of a passed type since there is no runtime checking after export to JS. The syntax uses a return type that is a predicate, which evaluates to a boolean, as shown in this internal method,

protected __isSortType(value: string, acceptable: Array): value is SortType

Usage is illustrated in the *setCriteria* mutator

valid = valid && this.__isSortType(criteria[i], values);

The TSMT Priority Queue supports addition and removal of items, removal of the first/last item in the queue, and clearing of the queue. By default, a sort is performed on each addition to the queue. The sort may be delayed by use of the *delay* mutator. Lazy validation is used in the class, so sorting may be delayed until calling a method that requires the queue to be in sorted order.

A generous set of specs is provided with the source distribution on Github and this is probably the best way to become familiar with using the priority queue. Even if you do not directly use the code, I hope you can borrow some of the Tyepscript techniques used in its development.

Enjoy!

]]>

JIT compilation, which is the norm for most examples posted online, is a process by which the compiler is shipped over the wire and templates are compiled inside the browser. While we are practically guaranteed a performance boost from AOT compilation, what about file size and load times? On the one hand, we gain from the fact that the compiler (which is a very large chunk of the platform) does not have to be sent over the wire. On the other hand, we lose from transforming the templates from very compact (and easily compressed) strings, to TS (and then ultimately into JS) factories. Now, the Angular team has done a great job of making the template factories VM friendly, however, this comes at the cost of more verbose code.

So, a general expectation is a performance gain and some file size reduction from the initial load of the platform and eagerly loaded routes. We also expect the file size of lazily-loaded routes to increase, but not by an uncomfortable amount. This should be offset by an increase in performance (i.e. reduced scripting and render time).

Let’s take a look at the entire process for the Three Stooges (lazy-loaded) micro-application. In the past, AOT compilation was a two-step process; compile the modules with ngc and then boot from the relevant app factory. This means either forking a separate project or adding *.jit.ts and *.aot.ts files to the project and then switching as needed to go back and forth from JIT to AOT compilation.

I do find generation of the factory files to be instructive and like to have it available, as illustrated by the *built-aot* command in my package.json.

Thankfully, the team working on the Angular2 CLI has done a phenomenal job of incorporating AOT compilation into existing projects with minimal source-code modification. I only had to make two changes to get the code working in production within the CLI. First, I removed template bindings to private class variables and methods in the app module. The former was accomplished by adding an accessor and then binding to the public accessor method. The latter was accomplished by using the */** @internal */* annotation and slight mods to the tsconfig.json. This does a fair job of accomplishing the required task while maintaining class encapsulation.

I also had to modify the routes for static analysis, which is a bit cumbersome if the CLI is installed globally. This is the hack.

There are a couple ways around this. I’m going to wait until the CLI is in production and then follow documented best practices at that time. I will then modify and release the source of this project to Github.

For the mean time, it is now a matter of using beta 24 of the CLI and the command

*ng-build –aot –prod –base-href /stoogesaot/*

There is no need to create a special boot module.

I deployed the code to my server and then ran some tests (clearing browser cache after each test). Keep in mind that these results were on my 2009 Macbook Pro. YMMV.

First, note that the file size of *main.<hash>.bundle.gz* went from 196K to 112K as a result of AOT compilation. For most environments with a big pipe, the difference in load time from the two would be considered minimal. For a SaaS environment where applications are served to hundreds of thousands or millions of users daily, the cumulative savings could be considered quite significant.

Here are the results of the initial load for the JIT application (two eagerly loaded routes). This is the minimum to put the application in front of the user.

(the idle time is delay from me stopping the recording

and the equivalent from the AOT-compiled version.

Load times between the two are pretty much within noise. Note the rather dramatic reduction in scripting and rendering time. For older machines (like my 2009 MBP) and mobile devices, this is significant.

Next, I recorded the process of clicking quickly between the remaining routes, ‘history’, ‘bios’, and ‘partial episode list’. I did note that file sizes for these chunks increased, but only by a modest margin and I could not detect any significant effect on load time between multiple runs of the two applications. Here are the performance results:

**JIT-Compiled**

**AOT-Compiled**

These templates (particularly the partial episode list) are more complex than those for the eagerly-loaded components. They require more effort to compile in-browser, so the performance difference from AOT compilation is pretty dramatic.

This really illustrates the beauty of the new Angular ecosystem. We have lazy-loading directly and efficiently supported in the platform and the ability to compile templates offline. The CLI is coming along very well with a 1.0 release expected soon. Rumor has it that the CLI may be eventually incorporated into WebStorm, which would provide a rich GUI for application development in Angular.

I feel confident in stating that 2017 will be the year of Angular.

]]>

*Consider the case of Katie, a ReactJS programmer who applied for a junior programmer job at company XYZ in Somewhere, USA. Katie had several React projects online, one of which was in Typescript, a relatively new language for her. During her phone interview, Katie was asked about React component life cycle, general programming concepts, and other things such as version control.*

*To her delight, Katie was invited for an on-site interview. After arriving, she was ushered to a conference room with a large white board. Several other developers came into the room and sat at one end of the table. One of the developers went to the board, and wrote a sequence of numbers,*

1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1

*Katie was then asked to write the pseudocode to compute the n-th row in this progression. Katie was not very strong in math and asked what this had to do with React or the position. She was told in a very stern voice that she would not be able to move forward in consideration for the position without coding the solution to this problem. Katie did not receive an offer.*

So, now Pascal’s Triangle is a programming test problem? I did look at her React portfolio and although my ReactJS is quite rusty, my belief is that Company XYZ lost out on a good junior programmer that would likely have been a very good long-term choice for them. All for the sake of developer ego and naivety.

Before I discuss the solution and my specific Typescript implementation, I suppose it’s natural to ask if I would have used this problem and if so, how would I have conducted the same interview. I bring this up since I’ve been involved in over a hundred developer interviews during my career and admit that a conducting a good interview is a constant learning process.

Since Katie is a junior developer, I’d be interested in the following during the course of a face-to-face interview.

– How much mentoring is Katie likely to need for tasks outside her direct experience?

– Can Katie help in brainstorming solutions to problems presented to our group?

– Does Katie grasp life-cycle concepts and how to implement solutions in an environment where multiple devs are working on a project?

– How well does Katie seem to ‘fit’ with the group?

If I have nothing else to work with (i.e. I know someone who worked with Katie or a detailed discussion with references), then I tend to prefer a combination of discussion problems and pair programming exercises for junior and intermediate-level positions. So, I might approach the interview as a simulation of our actual work environment where a customer presented a change request that requires Katie and myself to collaborate on solving the Pascal’s triangle problem. If there is interest, I might do another post on the sequence of questions I would ask and what I’m looking for in the answer and discussion resulting from each question. The bottom line is that there is no ‘me vs. Katie or us vs. the candidate vibe.’ I want to see how a junior person performs in a collaborative exercise since that is the exact environment in which they would be expected to work.

In the mean time, here is my solution to the Pascal’s triangle problem. My first attempt at this problem was in a computational geometry class in the 1980’s. I had to compute the *n-th* row to obtain the binomial coefficients needed to implement a *n-th* order Bezier curve. While we may deduce the forward recursion that allows row n to be generated from row *n-1*, it helps to have a proof that such a relationship always holds. Suppose we know nothing other than the arrangement of numbers, as presented. If we take it as axiomatic that each row begins and ends with a 1, then it is possible to create a proof by induction that the forward recurrence relation holds.

It helps, of course, to understand exactly what numbers comprise Pascal’s triangle, namely binomial coefficients. If *(n k)* represents the* k-th* element in the *n-th* row, then *(n k) = n! / k!(n-k)!* . This is the number of combinations of *n* items taken *k* at a time. The individual numbers in a row are coefficients in the expansion of *(x+y) ^{n}.*

Since *0! = 1! = 1*, all rows begin and end with a one, by definition. Proof of the forward recurrence (sometimes called Pascal’s rule) can be found elsewhere but is included here for completeness:

Show that *(n k) = (n-1 k-1) + (n-1 k)*

*(n-1 k-1) = (n-1)! / (k-1)!(n-1-(k-1))! = (n-1)! / (k-1)!(n-k)!*

*(n-1 k) = (n-1)! / k!(n-1-k)!*

Multiply the first expression by *(k/k)* and the second by *(n-k)/(n-k)*

*(n-1 k-1) + (n-1 k) = (n-1)![k + (n-k) / k!(n-k)!] = [n(n-1)!] / [k!(n-k)!] = n! / k!(n-k)! = (n k)*

for *k* in the closed interval *[1,n-1]*

This shows that the forward recurrence (i.e. computing row *n* from row *n-1*) holds. For convenience, we can hardcode the return for n = 0, 1, and 2 and then use Pascal’s rule for successive rows. The symmetry relationship follows directly from the definition of binomial coefficients, i.e. (n k) = (n n-k) for appropriate k.

This is essentially what I coded in Fortran in a first-semester computational geometry course.

In the early 2000’s, I had a business application that required frequent sampling of binomial coefficients for varying values of n and k. I modified the algorithm to cache the most recently computed row and then recurse forward from the beginning or the most recently computed row. If the next-requested value of n is the same as the cached version, then the appropriate coefficient can be returned from the cached row.

What is not generally seen in most discussions of Pascal’s triangle is that it is possible to recurse backwards, i.e. compute row n-1 from row n. The expression is

*(n k) = (n+1 k) – (n k-1)* and the corresponding code is easier if the leading 1 is maintained in the cached half-row.

To prove, expand the terms on the right-hand side of the equation and then multiply the second one by *k/k*. Then, factor out *n!* There should be an *(n+1-k)* term that cancels in numerator and denominator. I’m kind of skimming over this since I know most people will not be interested in this level of detail.

This leads to a very interesting algorithm where the recursion may be implemented from an initial row (2, for example) forward or from the currently cached row forward or backwards. This is the idea behind the Actionscript code I wrote way back in the day that was subsequently ported to JS and is now in the Typescript Math Toolkit.

You may deconstruct the implementation from the shared folder in the Typescript Programming Test Problems repo.

Enjoy, and the next time you are asked this problem in a programming test, ask the interviewer if they even know what those numbers are

]]>