aboutsummaryrefslogtreecommitdiff
path: root/hidden/2018-02-10-j-pascal.md
blob: 551a7b004bd8aeb087088f724f9c5fdbf1661a5a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
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!