diff options
| author | Fuwn <[email protected]> | 2020-11-06 18:24:26 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2020-11-06 18:24:26 -0800 |
| commit | 9cdce4254700691301608c6f1d3081950023cc4f (patch) | |
| tree | 9d24529acc19b354f80cb2d610aa1e7686f4d530 /hidden/2018-02-10-j-pascal.md | |
| download | blog-9cdce4254700691301608c6f1d3081950023cc4f.tar.xz blog-9cdce4254700691301608c6f1d3081950023cc4f.zip | |
repo: initial :star:
Diffstat (limited to 'hidden/2018-02-10-j-pascal.md')
| -rw-r--r-- | hidden/2018-02-10-j-pascal.md | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/hidden/2018-02-10-j-pascal.md b/hidden/2018-02-10-j-pascal.md new file mode 100644 index 0000000..551a7b0 --- /dev/null +++ b/hidden/2018-02-10-j-pascal.md @@ -0,0 +1,279 @@ +--- +title: Hello, J! Pascal's Triangle +route: /j-pascal +date: 2018-02-10 +description: +--- + +Following [my previous post on the Fibonacci numbers](/j-fibonacci), here's a quick post on generating another famous mathematical sequence - [Pascal's Triangle](https://en.wikipedia.org/wiki/Pascal%27s_triangle). + +``` + 1 + 1 1 + 1 2 1 + 1 3 3 1 +1 4 6 4 1 +``` + +## Quick Background + +Pascal's triangle contains numbers formed by binomial coefficients (often referred to as "N choose K"), but there's a simple and elegant way to generate it: **each item is the sum of the two numbers above it**. + +<pre> + 1 <span style="border:1px solid black">3 3</span> 1 +1 4 <u>6</u> 4 1 +</pre> + +We see here that the underlined 6 is formed by adding the two threes above it. + +<pre> + <span style="border:1px solid black">1 3</span> 3 <span style="border:1px solid black">1 </span> +1 <u>4</u> 6 4 <u>1</u> +</pre> + +Similarly, we see the 4 is formed by adding the 1 and 3, and the 1 is formed by adding 1 to nothing (0). + +## Summing pairs + +Before we get started go ahead and [grab yourself a copy of the J runtime](http://code.jsoftware.com/wiki/System/Installation/All-in-One) if you haven't already. + +Let's start by grabbing the first 5 integers using the ["integers" verb `i.`](http://www.jsoftware.com/help/dictionary/didot.htm) + +``` + i. 5 +0 1 2 3 4 +``` + +We can use the ["same" verb `]`](http://www.jsoftware.com/help/dictionary/d500.htm) to echo whatever we pass into it. + +``` + ] 10 +10 + ] i.5 +0 1 2 3 4 +``` + +Our primary tool will be J's [infix adverb `\`](http://www.jsoftware.com/help/dictionary/d430.htm). This single backslash allows us to scan through a list of numbers in groups and apply a function to them. + +Let's scan every 3 items and pass them to the "same" verb `]`. + +``` + 3 ]\ i.5 +0 1 2 +1 2 3 +2 3 4 +``` + +We can see here that J looks through `0 1 2 3 4` in overlapping groups of 3. So we'll have `0 1 2`, followed by `1 2 3`, etc. + +By changing the number in front, we can scan in groups of 2. + +``` + 2 ]\ i.5 +0 1 +1 2 +2 3 +3 4 +``` + +Let's swap out our boring `]` for something more interesting: `+/`, which sums a list of numbers. + +``` + 3 +/\ i.5 +3 6 9 + +/ 0 1 2 +3 + +/ 1 2 3 +6 + +/ 2 3 4 +9 +``` + +Similarly, we can do this pairwise. + +``` + 2 +/\ i.5 +1 3 5 7 +``` + +Pretty nifty right? + +## Row after row + +So why is this useful? Well, if we take another look at our triangle: + +``` + 1 + 1 1 + 1 2 1 + 1 3 3 1 +1 4 6 4 1 +``` + +We can see that the next row, `1 5 10 10 5 1` can be formed by this exact strategy: summing each pair of numbers to generate the number beneath it. + +``` + 2 +/\ 1 3 3 1 +4 6 4 + 2 +/\ 1 4 6 4 1 +5 10 10 5 +``` + +Well, almost. Our issue is that we're missing out on the 1s on either side! This is because our infix operator `\` starts with `+/ 1 4` to get 5 - skipping over the 1. + +To fix this, let's surround our row with 0s. + +``` + 2 ]\ 0 1 3 3 1 0 +0 1 +1 3 +3 3 +3 1 +1 0 + 2 +/\ 0 1 3 3 1 0 +1 4 6 4 1 + 2 +/\ 0 1 4 6 4 1 0 +1 5 10 10 5 1 +``` + +Much better. So how do we surround with 0s automatically? + +The [append verb `,`](http://www.jsoftware.com/help/dictionary/d320.htm) is used to join items and lists. + +``` + 0 , 1 +0 1 + 1 2 3 , 7 8 9 +1 2 3 7 8 9 +``` + +The ["bond" verb `&`](http://www.jsoftware.com/help/dictionary/d630n.htm) allows us to partially evaluate a verb that normally expects items on both sides. + +``` + 1 + 2 +3 + (1&+) 2 +3 + 4 % 2 NB. "%" is division! +2 + (%&2) 4 +2 +``` + +We can bind our append verb to add a 0 to either side. + +``` + (0&,) 5 6 7 +0 5 6 7 + (,&0) 5 6 7 +5 6 7 0 +``` + +We can also do both. + +``` + (0&,) (,&0) 5 6 7 +0 5 6 7 0 + (,&0) (0&,) 5 6 7 +0 5 6 7 0 +``` + +Putting it all together: we can append 0 on either side of our row: + +``` + (0&,) (,&0) 1 4 6 4 1 +0 1 4 6 4 1 0 +``` + +And sum each pair: + +``` + 2 +/\ (0&,) (,&0) 1 4 6 4 1 +1 5 10 10 5 1 +``` + +## All together now + +Let's wrap this in our own verb called `next`. "`y`" gives us access to the argument(s) passed in. + +``` + next =: verb : '2 +/\ (0&,) (,&0) y' + next 1 3 3 1 +1 4 6 4 1 + next 1 4 6 4 1 +1 5 10 10 5 1 +``` + +Fortunately, `next` works just fine on the first row of our triangle: a single `1`. + +``` + next 1 +1 1 +``` + +We can apply `next` multiple times. + +``` + next 1 +1 1 + next 1 1 +1 2 1 + next next 1 +1 2 1 + next next next next 1 +1 4 6 4 1 +``` + +We can use the ["power" verb `^:`](http://www.jsoftware.com/help/dictionary/d202n.htm) to do this for us. + +``` + (next^:0) 1 +1 + (next^:1) 1 +1 1 + (next^:5) 1 +1 5 10 10 5 1 +``` + +We can also pass a list to `^:` to generate multiple powers at the same time. + +``` + (next^:(i.7)) 1 +1 0 0 0 0 0 0 +1 1 0 0 0 0 0 +1 2 1 0 0 0 0 +1 3 3 1 0 0 0 +1 4 6 4 1 0 0 +1 5 10 10 5 1 0 +1 6 15 20 15 6 1 +``` + +We can store this as another verb to generate Pascal's Triangle. We’ll also simplify our definition of next using the ["atop" verb `@`](http://www.jsoftware.com/help/dictionary/d620.htm). + +``` + next =: 2 +/\ (0&,) @ (,&0) + pascal =: verb : '(next^:(i.y)) 1' + NB. We can also inline `next` entirely + pascal =: verb : '((2 +/\ (0&,) @ (,&0))^:(i.y)) 1' + pascal 10 +1 0 0 0 0 0 0 0 0 0 +1 1 0 0 0 0 0 0 0 0 +1 2 1 0 0 0 0 0 0 0 +1 3 3 1 0 0 0 0 0 0 +1 4 6 4 1 0 0 0 0 0 +1 5 10 10 5 1 0 0 0 0 +1 6 15 20 15 6 1 0 0 0 +1 7 21 35 35 21 7 1 0 0 +1 8 28 56 70 56 28 8 1 0 +1 9 36 84 126 126 84 36 9 1 +``` + +🎉 🎉 + +Thanks to the powers of `\` and `^:`, we can intuitively generate Pascal's Triangle in a few dozen characters. + +J makes operations on lists and matrices a breeze, and contains a number of interesting ideas for function composition and application. I hope you found this post interesting and give a look at what J has to offer. + +I think you'll be pleasantly surprised at how fun it is. + +Thanks for reading! |