💾 Archived View for tranarchy.fish › ~autumn › apl2 › chapter6.gmi captured on 2023-03-20 at 17:51:19. Gemini links have been rewritten to link to archived content

View Raw

More Information

➡️ Next capture (2023-04-19)

-=-=-=-=-=-=-

<- Back to APL2 at a Glance

Chapter 6: Working with Data

<header>

<table width=100%>

<tr>

<td style="text-align: left">

[<a href="chapter5.html"><code>←</code></a>]

</td>

<td style="text-align: center">

[<a href="contents.html"><code>↑</code></a>]

</td>

<td style="text-align: right">

[<a href="chapter7.html"><code>→</code></a>]

</td>

</tr>

</table>

</header>

<div class="chapter-rule">

<hr class="chapter-long">

<p>Chapter</p>

<hr class="chapter-short">

<div>

<div>

6

</div>

</div>

</div>

<h2>Working with Data</h2>

<p>You’ve seen ways to build collections of data and ways to select subsets of data. In handling data, you may find it useful to compare array items, select particular items in an array, omit items, and search and sort through arrays for specified information. This chapter helps you understand how to use <span class="small-caps">APL2</span> functions to perform such operations and how to manipulate name assignments to replace values in variables. For work with numeric data, it presents five more computational functions and expands on the <strong>power</strong> function introduced in <a href="chapter2.html">Chapter 2</a>.</p>

<h3 id="section-6.1-ways-of-comparing">Section 6.1 — Ways of Comparing<a href="#section-6.1-ways-of-comparing" class="section-link">§</a></h3>

<p>This section shows you how to do various comparisons with relational functions, the matching function, and Boolean functions. In <span class="small-caps">APL2</span>, when a comparison is true, the result is <code>1</code>. When a comparison is not true, the result is <code>0</code>. One and zero are sometimes called <em>truth values</em>. In <span class="small-caps">APL2</span>, truth values are just numbers and can be used in computations just like any other numbers.</p>

<h4 id="relational-functions">Relational Functions<a href="#relational-functions" class="section-link">§</a></h4>

<p>The relational functions are dyadic scalar functions that compare groups of data. The following table summarizes the <span class="small-caps">APL2</span> relational functions:</p>

<table>

<caption>Table 6.1 APL2 Relational Functions</caption>

<thead>

<tr class="header">

<th style="text-align: center;">Symbol</th>

<th style="text-align: left;">Name</th>

</tr>

</thead>

<tbody>

<tr>

<td class="l t r" style="text-align: center;"><code>&lt;</code></td>

<td class="l t r" style="text-align: left;"><strong>less than</strong></td>

</tr>

<tr>

<td class="l r" style="text-align: center;"><code>≤</code></td>

<td class="l r" style="text-align: left;"><strong>less than or equal</strong></td>

</tr>

<tr>

<td class="l r" style="text-align: center;"><code>&gt;</code></td>

<td class="l r" style="text-align: left;"><strong>greater than or equal</strong></td>

</tr>

<tr>

<td class="l r" style="text-align: center;"><code>≥</code></td>

<td class="l r" style="text-align: left;"><strong>greater than</strong></td>

</tr>

<tr>

<td class="l r" style="text-align: center;"><code>=</code></td>

<td class="l r" style="text-align: left;"><strong>equal</strong></td>

</tr>

<tr>

<td class="l r b" style="text-align: center;"><code>≠</code></td>

<td class="l r b" style="text-align: left;"><strong>not equal</strong></td>

</tr>

</tbody>

</table>

<p>Here are some examples of the relational functions:</p>

<pre> 3&lt;2

0

3 4 5 &gt; 4 10 2

0 0 1

5 &gt; 4 10 2

1 0 1</pre>

<p>Since the results of relational functions are numbers, these functions may be used in arithmetic expressions. Here is an example:</p>

<pre> R1←10 0 20

100÷R1+0=R1

10 100 5</pre>

<p>This expression divides <code>100</code> by a vector and avoids an error where the vector contains a zero.</p>

<p>The relational functions are scalar functions. They all work the same way on nested arrays. The function is applied between simple scalars, giving a nested result:</p>

<pre> 10 20 = (18 10 20) (10 30 20)

0 1 0 0 0 1</pre>

<p>Only <strong>equal</strong> and <strong>not equal</strong> can be applied to character data:</p>

<pre> 'ABCD' = 'ABCE'

1110

'ABCD' = 'ABCE'

0001</pre>

<p>Be careful when using <strong>equal</strong> to compare nested character vectors. You might think that the following expression would give the answer <code>1 0</code>:</p>

<pre> 'JANE' 'JIM' = 'JANE' 'JOHN'</pre>

<p>However, when <code>'JANE'</code> is compared to <code>'JANE'</code> you get a result of <code>1 1 1 1</code>, and when <code>'JIM'</code> is compared to <code>'JOHN'</code> you get a <code>LENGTH ERROR</code>. Even if you fixed the example to avoid the <code>LENGTH ERROR</code>, you would not get the result <code>1 0</code>. Here is an example:</p>

<pre> 'JANE' 'JIM' = 'JANE' 'JOE'

1 1 1 1 1 0 0 </pre>

<p>The next section shows how to get the comparison you want.</p>

<p>You must exercise care when using the relational functions with numbers resulting from a computation. Machine arithmetic is not always exact. For example, the result of the expression <code>1÷3</code> requires an infinite number of digits to represent it as a decimal fraction. <span class="small-caps">APL2</span> adjusts the relational functions for small inaccuracies. Here is an example:</p>

<pre> .3333333333333 = .33333333333333

1</pre>

<p>The numbers are not really equal (the first number has 13 digits and the second, 14 digits), but they are close enough. Exactly how close two numbers need to be before <span class="small-caps">APL2</span> calls them equal depends on the machine architecture and the <span class="small-caps">APL2</span> implementation.</p>

<p>The relational functions all do a “close enough” comparison and so they are called <em>fuzzy functions</em> and the two numbers in the example just shown are said to be equal within <em>fuzz</em> (also called the <em>comparison tolerance</em>). This book does not discuss the precise definition of fuzz. Comparisons with zero are never fuzzed, so if you want exact comparisons, compare against zero:</p>

<pre> .3333333333333 = .33333333333333

1

.3333333333333 − .33333333333333

¯3.000377724E¯14

0=.3333333333333 − .33333333333333

0</pre>

<p>The above example shows that although the two given numbers are equal within fuzz, their difference is not zero. The actual number you get for the subtraction depends on the system you are using.</p>

<h4 id="match">Match<a href="#match" class="section-link">§</a></h4>

<p>The function <strong>match</strong> (<code>≡</code>) is like the relational functions in that it returns a <code>1</code> or a <code>0</code>. It is different because it always returns a single <code>1</code> or a single <code>0</code> depending on whether its arguments have the same value and the same structure.</p>

<p>On simple scalars, <strong>match</strong> is the same as <strong>equal</strong>:</p>

<pre> 5 ≡ 5

1

3 ≡ 4

0</pre>

<p>On other arrays, <strong>match</strong> returns a <code>1</code> only if the two arguments have the same shape and corresponding items match:</p>

<pre> 'JIM' ≡ 'JOHN'

0

2 3 (4 5) ≡ 1 + 1 2 (3 4)

1</pre>

<p>You sometimes want to know whether two arrays (say, <code>X</code> and <code>Y</code>) have the same shape. You might be tempted to write:</p>

<pre> (⍴X) = (⍴Y)</pre>

<p>But if <code>X</code> and <code>Y</code> have different rank, this expression will yield a <code>LENGTH ERROR</code>. Instead, write this:</p>

<pre> (⍴X) ≡ (⍴Y)</pre>

<p>In the discussion of the relational functions, you saw that the following example gave a <code>LENGTH ERROR</code> when you wanted the result <code>1 0</code>:</p>

<pre> 'JANE' 'JIM' = 'JANE' 'JOHN'

LENGTH ERROR

'JANE' 'JIM' = 'JANE' 'JOHN'

^ ^</pre>

<p>Can you use <strong>match</strong> to produce the desired result?</p>

<pre> 'JANE' 'JIM' = 'JANE' 'JOHN'

0</pre>

<p>No.&nbsp;<strong>Match</strong> compares the arguments for value and structure. The argument <code>'JANE' 'JIM'</code> does not match the argument <code>'JANE' 'JOHN'</code> in value and structure. Therefore, <strong>match</strong> returns a 0. What you really want is to match items in corresponding positions. To do that, you use <strong>match-each</strong>:</p>

<pre> 'JANE' 'JIM' ≡¨ 'JANE' 'JOHN'

1 0</pre>

<p><strong>Match-each</strong> does what your intuition might say <strong>equal</strong> should do. <strong>Equal</strong> is a scalar function so it works like all the other scalar functions.</p>

<h4 id="a-boolean-functions">A Boolean Functions<a href="#a-boolean-functions" class="section-link">§</a></h4>

<p>You’ve just seen a set of functions that return, as results, arrays of truth values—<code>0</code>’s and <code>1</code>’s. Such arrays are <em>Boolean arrays</em> (named after George Boole, who invented Boolean algebra). The Boolean functions are a set of functions that, given Boolean arrays, produce Boolean arrays. The following tables summarize the Boolean functions:</p>

<table>

<caption>Table 6.2 Dyadic Boolean Functions</caption>

</colgroup>

<thead>

<tr class="header">

<th style="text-align: center;">Symbol</th>

<th style="text-align: left;">Name</th>

<th style="text-align: left;">Produces <code>1</code> if</th>

</tr>

</thead>

<tbody>

<tr>

<td class="l t r" style="text-align: center;"><code>∧</code></td>

<td class="l t r" style="text-align: left;"><strong>and</strong></td>

<td class="l t r" style="text-align: left;">Both arguments are <code>1</code></td>

</tr>

<tr>

<td class="l r" style="text-align: center;"><code>∨</code></td>

<td class="l r" style="text-align: left;"><strong>or</strong></td>

<td class="l r" style="text-align: left;">Either argument is <code>1</code></td>

</tr>

<tr>

<td class="l r" style="text-align: center;"><code>⍲</code></td>

<td class="l r" style="text-align: left;"><strong>nand</strong></td>

<td class="l r" style="text-align: left;">Both arguments are <code>0</code></td>

</tr>

<tr>

<td class="l r" style="text-align: center;"><code>⍱</code></td>

<td class="l r" style="text-align: left;"><strong>nor</strong></td>

<td class="l r" style="text-align: left;">Either argument is <code>0</code></td>

</tr>

<tr>

<td class="l r" style="text-align: center;"><code>=</code></td>

<td class="l r" style="text-align: left;"><strong>equal</strong></td>

<td class="l r" style="text-align: left;">Both arguments are the same</td>

</tr>

<tr>

<td class="l r b" style="text-align: center;"><code>≠</code></td>

<td class="l r b" style="text-align: left;"><strong>exclusive or</strong></td>

<td class="l r b" style="text-align: left;">Either but not both are <code>1</code></td>

</tr>

</tbody>

</table>

<p>Notice that <code>=</code> and <code>≠</code> can be considered either Boolean or relational. If you think comparisons, <code>≠</code> is <strong>not equal</strong>. If you think truth values, <code>≠</code> is <strong>exclusive or</strong>.</p>

<p>There is one monadic Boolean function:</p>

<table>

<caption>Table 6.3 Monadic Boolean Functions</caption>

</colgroup>

<thead>

<tr class="header">

<th style="text-align: center;">Symbol</th>

<th style="text-align: left;">Name</th>

<th style="text-align: left;">Produces <code>1</code> if</th>

</tr>

</thead>

<tbody>

<tr>

<td class="l t r b" style="text-align: center;"><code>∼</code></td>

<td class="l t r b" style="text-align: left;"><strong>not</strong></td>

<td class="l t r b" style="text-align: left;">argument is <code>0</code></td>

</tr>

</tbody>

</table>

<p>Here are some examples of the Boolean functions:</p>

<pre> 0 1 0 1 ∧ 0 0 1 1

0 0 0 1

0 1 0 1 ≠ 0 0 1 1

0 1 1 0</pre>

<p>The Boolean functions are easy to implement in electronic circuits, and so they are the functions that describe most of the hardware in a digital computer.</p>

<p>The Boolean functions are useful in making connections between relational expressions. For example, suppose you wanted to know which products cost less than $10 but more than $7:</p>

<pre> RETAIL←6.95 7.95 12.95

RETAIL&lt;10

1 1 0

RETAIL&gt;7

0 1 1</pre>

<p>You can connect these into one expression using <strong>and</strong>. Here is an expression that gives <code>1</code> for a product that costs more than $7.00 but less than $10:</p>

<pre> (RETAIL&lt;10) ∧ (RETAIL&gt;7)

0 1 0</pre>

<p>In combinations with the <strong>reduction</strong> operator (<code>/</code>), the Boolean functions can answer some interesting questions.</p>

<blockquote>

<p>Do all products cost less than $10?</p>

<pre> ∧/RETAIL&lt;10

0</pre>

<p>Does any product cost less than $10?</p>

<pre> ∨/RETAIL&lt;10

1</pre>

</blockquote>

<p>Given a Boolean vector, an <strong>exclusive-or-reduction</strong> (<code>≠/</code>) tells you whether there is an odd number of <code>1</code>’s:</p>

<pre> ≠/ 1 0 1 1 0 1 0 0

0

≠/ 1 0 1 1 0 1 0 0 1

1</pre>

<p>Checking for an odd number of <code>1</code>’s is a <em>parity check</em>. Be sure you can figure out these last two examples. They can help you improve your understanding of <strong>reduction</strong>.</p>

<p><strong>Not</strong> (<code>∼</code>) can be used to select a complementary set. For example, if you want to produce a 1 when two arrays are not identical, apply <strong>not</strong> to <strong>match</strong>:</p>

<pre> A←'ONE'

B←'ANOTHER'

∼A≡B

1</pre>

<p>To determine products that don’t cost in the range from 7 to 10 dollars, you could enter:</p>

<pre> ∼(RETAIL&lt;10) ∧ (RETAIL&gt;7)

1 0 1</pre>

<p>This can be expressed more compactly using <strong>nand</strong>:</p>

<pre> (RETAIL&lt;10) ⍲ (RETAIL&gt;7)

1 0 1</pre>

<p>Some interesting derived functions arise from applying the <strong>scan</strong> (<code>\</code>) operator to Boolean functions.</p>

<p><strong>And-scan</strong> (<code>∧\</code>) keeps leading <code>1</code>’s in a Boolean vector. Any <code>1</code>’s after the first <code>0</code> are set to <code>0</code>:</p>

<pre> ∧\1 1 1 1 0 1 0 1 1

1 1 1 1 0 0 0 0 0</pre>

<p><strong>Or-scan</strong> (<code>∨\</code>) does a similar operation for <code>0</code>’s; that is, <strong>or-scan</strong> keeps the leading <code>0</code>’s but changes other <code>0</code>’s to <code>1</code>’s.</p>

<pre> ∨\0 0 0 0 1 0 1 0 1

0 0 0 0 1 1 1 1 1</pre>

<p><strong>Exclusive-or-scan</strong> or <strong>not equal-scan</strong> (<code>≠\</code>) spreads <code>1</code>’s over <code>0</code>’s until the next <code>1</code>:</p>

<pre> ≠\0 0 0 1 0 0 1 0 0 0 1 0 0

0 0 0 1 1 1 0 0 0 0 1 1 1</pre>

<p>An <strong>and-scan</strong> (<code>∧\</code>) is used in an expression that deletes leading blanks from a character string. The following example shows the construction of the expression:</p>

<pre> TX←' LEADING BLANKS '

TX=' '

1 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1

∧\TX=' '

1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

+/∧\TX=' '

6

(+/∧\TX=' ')↓TX

LEADING BLANKS </pre>

<h4 id="exercises-for-section-6.1">Exercises for Section 6.1<sup class="answers-note">[<a href="answers.html#section-6.1-ways-of-comparing">Answers</a>]</sup><a href="#exercises-for-section-6.1" class="section-link">§</a></h4>

<ol>

<li><p>Write an expression to count the number of simple scalar 0’s in an array.</p></li>

<li><p>Write an expression to compute the magnitude of a vector without using the <strong>magnitude</strong> function. Test your application with the vector <code>V← ¯21 23 0 ¯1</code></p></li>

<li><p>Write the <span class="small-caps">APL2</span> expression that will produce the results shown in the columns of the following table. Your expressions should contain at most one <span class="small-caps">APL2</span> relational or Boolean function and either <code>A</code> or <code>B</code> or both <code>A</code> and <code>B</code>. <code>A</code> and <code>B</code> have the following values:</p>

<pre> A← 0 0 1 1

B← 0 1 0 1</pre>

<p>For example, to compute the result in column 2. use the expression <code>A∧B</code>.</p>

<pre>A B │ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

────┼──────────���────────────────────────────

0 0 │ 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

0 1 │ 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1

1 0 │ 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1

1 1 │ 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1</pre></li>

<li><p>Using the variable <code>RETAIL</code>, write an expression to calculate how many products cost less than 10 dollars.</p></li>

<li><p>Write an expression to return a <code>1</code> if a number <code>N</code> is an integer.</p></li>

<li><p>Investigate the result of applying <strong>less than-scan</strong> (<code>&lt;\</code>) to Boolean vectors. How would you describe the function performed?</p></li>

<li><p>Write a function called <code>COUNTVOWELS</code> to count the number of vowels in a character string and calculate the ratio of vowels to characters in the string. Display the result as a three-column table. The first column should be the vowels (AEIOUY); the second column should be the number of occurrences of that vowel in the string; and the third column should display the ratio as a percentage truncated to a whole number. Your function should produce a result as follows:</p>

<pre> COUNTVOWEL 'A ROSE IS NOT A DAISY'

NUMBER PERCENT

A 4 17

E 1 4

I 2 8

O 2 8

U 0 0

Y 1 4</pre></li>

<li><p>Predict the result, shape, and depth of the following expressions. Explain any errors that would occur:</p>

<ol type="a">

<li><code>'SMITH'='SMITH'</code></li>

<li><code>'SMITH'='SMYTH'</code></li>

<li><code>'SMITH'='SMITHY'</code></li>

<li><code>'SMITH'≡'SMITH'</code></li>

<li><code>'SMITH'≡'SMYTH'</code></li>

<li><code>'SMITH'≡'SMITHY'</code></li>

<li><code>'APL2'≡'APL2'</code></li>

<li><code>'APL2'≡'APL2 '</code></li>

<li><code>1 2 3 4 5 ≡ 1 2 3 4 5</code></li>

<li><code>1 2 3 4 5 ≡ 1 2 3 (4 5)</code></li>

<li><code>1 2 3 'AB' ≡ 1 2 3 ('AB')</code></li>

<li><code>'ABC' (4 5)≡(4 5) 'ABC'</code></li>

<li><code>'ROY' 'SMITH' = 'ROB' 'SMITH'</code></li>

<li><code>'ROY' 'SMITH' ≡ 'ROB' 'SMITH'</code></li>

<li><code>'ROY' 'SMITH' ≡¨ 'ROB' 'SMITH'</code></li>

<li><code>'ALAN' 'RAY' = 'A'</code></li>

</ol></li>

<li><p>In logic, the statement “If P is true, then Q is true” is called <em>implication</em>. Another way of phrasing this statement is “If P is false, then Q may be either true or false.”</p>

<ol type="a">

<li>Write an expression to compute the truth table for implication using the functions <code>∨</code> and <code>∼</code>.</li>

<li>What single <span class="small-caps">APL2</span> function also yields implication?</li>

</ol></li>

<li><p>Write an expression that produces an array with the same values as <code>M</code> except that <code>0</code>’s are replaced by <code>1</code>’s.</p></li>

<li><p>Write an expression to round up any positive number as follows:</p>

<ol type="a">

<li><p>To the next higher multiple of .5.</p></li>

<li><p>To the nearest multiple of .5.</p>

<p>For example,</p>

<pre> V←2 2.3 2.5 2.7 3 3.1</pre>

<p>(a) results in <code>2.5 2.5 3 3 3.5 3.5</code><br>

(b) results in <code>2 2.5 2.5 3 3 3</code></p></li>

</ol></li>

</ol>

<h3 id="section-6.2-selecting-subsets-of-arrays">Section 6.2 — Selecting Subsets of Arrays<a href="#section-6.2-selecting-subsets-of-arrays" class="section-link">§</a></h3>

<p>Selecting and working with subsets is a fundamental activity when you deal with array data structures. This section discusses these operations for selecting and working with subsets:</p>

<ul>

<li><strong>indexing</strong></li>

<li><strong>replicate</strong></li>

<li><strong>expand</strong></li>

<li><strong>without</strong></li>

<li><strong>selective assignment</strong></li>

</ul>

<h4 id="indexing">Indexing<a href="#indexing" class="section-link">§</a></h4>

<p>As you have learned, <span class="small-caps">APL2</span> arrays are ordered collections of data. In a vector, there is conceptually a first item, a second item, and so forth. In a matrix, there is conceptually a first row, a first column, a second row, a second column, and so forth. This ordering makes it possible to identify any item in an array by using a set of integers to indicate the position in the array. This set of integers is the <em>index</em> of the item in the array. Mathematicians use the term <strong><em>subscript</em></strong> for the same concept.</p>

<p><a href="chapter2.html">Chapter 2</a> explained <strong>indexing</strong> applied to vectors. Here is an example:</p>

<pre> 'TAPES'[3 2 5 1 4]

PASTE

'TAPES'[1 4 2]

TEA</pre>

<p>When you want to index a rank-<code>N</code> array, you must specify an integer for each of the axes. With the <strong>indexing</strong> function, these <code>N</code> numbers are written inside the square brackets and are separated by semicolons. For example, to select the item in row 2, column 3, of a matrix, you enter</p>

<pre> AC← 3 4⍴'ABCDEFGHIJKL'

AC

ABCD

EFGH

IJKL

AC[2;3]

G</pre>

<p>To select a cross-section of items, you specify a vector of indices in one or more of the index positions. Here’s an expression that selects both column 1 and column 3 from row 2 of matrix <code>AC</code>:</p>

<pre> AC[2;1 3]

EG</pre>

<p>When you specify more than one number in any index position, you are requesting that these numbers be used together with the numbers in the other index positions in all combinations. Therefore, if you index two of the rows and three of the columns in a matrix, you select six items:</p>

<pre> AC[2 3;2 3 4]

FGH

JKL</pre>

<p>Here is a diagram of this selection:</p>

<center>

<img src="images/multi_index.png">

</center>

<p>You can, of course, select an entire row of a matrix by specifying that row and every column in order:</p>

<pre> AC[2;1 2 3 4]

EFGH</pre>

<p>You can indicate the selection of every item along some axis more concisely by putting no value in the index position. Using this notation, you can select every item in row 2:</p>

<pre> AC[2;]

EFGH</pre>

<p>Here’s an example that selects every row of columns 1 and 3:</p>

<pre> AC[;1 3]

AC

EG

IK</pre>

<p>Leaving out an index is equivalent to writing a vector of integers from <code>1</code> up to the length of the axis.</p>

<p>In the preceding two examples, the indices left out are equivalent, respectively, to these expressions:</p>

<pre> ⍳ (⍴AC)[2]

1 2 3 4

⍳ (⍴AC)[1]

1 2 3</pre>

<p>Eliding an axis selects all items along the corresponding axis. Therefore:</p>

<pre> AC[2;] &lt;--&gt; AC[2;⍳(⍴AC)[2]]

AC[;1 3] &lt;--&gt; AC[⍳(⍴AC)[1],1 3]</pre>

<p>So far, the examples of <strong>indexing</strong> have used only scalars and vectors as indices. Higher rank arrays may also be used as indices. Here are two examples where a matrix is used to index a matrix:</p>

<pre> AC[2;2 2⍴ 1 3 1 2]

EG

EF

AC[2 1;2 2⍴ 1 3 1 2]

EG

EF

AC

AB</pre>

<p>With such generality in the indices, it may seem difficult to predict the kind of array that a given application of <strong>indexing</strong> produces. In fact, however, computing the result of <strong>indexing</strong> is easy if you remember the following rules about rank and shape.</p>

<ol>

<li><p>Rank of <strong>indexing</strong>: The rank of the result of <strong>indexing</strong> is the sum of the ranks of the indices. The rank of an elided index is one.</p>

<p>The following examples show this rule applied to some of the previous examples:</p>

<table>

<thead>

<tr class="header">

<th class="l t r b" style="text-align: left;">Expression</th>

<th class="l t r b" style="text-align: center;">Rank</th>

<th class="l t r b" style="text-align: left;">Reason</th>

</tr>

</thead>

<tbody>

<tr>

<td class="l t r b" style="text-align: left;"><pre>AC[2;3]</pre></td>

<td class="l t r b" style="text-align: center;"><code>0</code></td>

<td class="l t r b" style="text-align: left;"><pre>(⍴⍴2)+(⍴⍴3)

0 + 0</pre></td>

</tr>

<tr>

<td class="l t r b" style="text-align: left;"><pre>AC[2;1 3]</pre></td>

<td class="l t r b" style="text-align: center;"><code>1</code></td>

<td class="l t r b" style="text-align: left;"><pre>(⍴⍴2)+(⍴⍴1 3)

0 + 1</pre></td>

</tr>

<tr>

<td class="l t r b" style="text-align: left;"><pre>AC[2 3;2 3 4]</pre></td>

<td class="l t r b" style="text-align: center;"><code>2</code></td>

<td class="l t r b" style="text-align: left;"><pre>(⍴⍴2 1)+(⍴⍴MI)

1 + 2</pre></td>

</tr>

<tr>

<td class="l t r b" style="text-align: left;"><pre>MI←3 4⍴ 1 3 4 2 1

AC[2 1;MI]</pre></td>

<td class="l t r b" style="text-align: center;"><code>3</code></td>

<td class="l t r b" style="text-align: left;"><pre>(⍴⍴2 1)+(⍴⍴MI)

1 + 2</pre></td>

</tr>

<tr>

<td class="l t r b" style="text-align: left;"><pre>AC[;2 3]</pre></td>

<td class="l t r b" style="text-align: center;"><code>2</code></td>

<td class="l t r b" style="text-align: left;"><pre>((⍳⍴⍴AC)[1])+(⍴⍴2 3)

1 + 1</pre></td>

</tr>

</tbody>

</table>

</li>

<li><p><strong>Shape of indexing</strong>: The shape of the result of <strong>indexing</strong> is the catenate of the shapes of the indices. The shape of an elided index is the length of the axis corresponding to that index.</p>

<p>The following examples show this rule applied to the same expressions as the examples for rule 1:</p>

<table>

<thead>

<tr class="header">

<th class="l t r b" style="text-align: left;">Expression</th>

<th class="l t r b" style="text-align: center;">Shape</th>

<th class="l t r b" style="text-align: left;">Reason</th>

</tr>

</thead>

<tbody>

<tr>

<td class="l t r b" style="text-align: left;"><pre>AC[2;3]</pre></td>

<td class="l t r b" style="text-align: center;"><code>⍳0</code> (empty)</td>

<td class="l t r b" style="text-align: left;"><pre>(⍴2),(⍴3)

(⍳0),(⍳0)</pre></td>

</tr>

<tr>

<td class="l t r b" style="text-align: left;"><pre>AC[2;1 3]</pre></td>

<td class="l t r b" style="text-align: center;"><code>,2</code></td>

<td class="l t r b" style="text-align: left;"><pre>(⍴2),(⍴1 3)

(⍳0),(,2)</pre></td>

</tr>

<tr>

<td class="l t r b" style="text-align: left;"><pre>AC[2 3;2 3 4]</pre></td>

<td class="l t r b" style="text-align: center;"><code>2 3</code></td>

<td class="l t r b" style="text-align: left;"><pre>(⍴2 1),(⍴MI)

(,2) ,(,3)</pre></td>

</tr>

<tr>

<td class="l t r b" style="text-align: left;"><pre>MI←3 4⍴ 1 3 4 2 1

AC[2 1;MI]</pre></td>

<td class="l t r b" style="text-align: center;"><code>2 3 4</code></td>

<td class="l t r b" style="text-align: left;"><pre>(⍴2 1),(⍴MI)

(,2) ,(3 4)</pre></td>

</tr>

<tr>

<td class="l t r b" style="text-align: left;"><pre>AC[;2 3]</pre></td>

<td class="l t r b" style="text-align: center;"><code>3 2</code></td>

<td class="l t r b" style="text-align: left;"><pre>(⍴AC)[1],⍴2 3

3 , (,2)</pre></td>

</tr>

</tbody>

</table>

</li>

<li><p>Values selected by <strong>indexing</strong>: Once you know the rank and | shape of the result, you can easily compute the values. The first item of the result is the item indicated by the first item of each index. The remaining items of the result come from using the indices in order. A given index has all its values used for a fixed value from the index to its left.</p>

<p>Here is a diagram in the shape of the result of the operation <code>AC[2 1;MI]</code>. Each position is labeled with the row and column index used to select an item for the result:</p>

<center>

<img src="images/indexing_3.png">

</center>

<pre> AC←3 4⍴'ABCDEFGHIJKL'

MI←3 4⍴ 1 3 4 2 1

AC[2 1;MI]

EGHF

EEGH

FEEG

ACDB

AACD

BAAC</pre></li>

</ol>

<p>An attempt to select an item that doesn’t exist gives the message <code>INDEX ERROR</code>:</p>

<pre> 'ABC'[5]

INDEX ERROR

'ABC'[5]

∧ ∧</pre>

<p>You can use <strong>indexing</strong> to plot simple graphs. For example, suppose the variable <code>SALES</code> represents the number of computer systems that a company sold each month in its first year of operation:</p>

<pre> SALES←1 0 3 5 2 7 10 7 10 5 3 2</pre>

<p>Comparing these monthly sales numbers in all combinations with the integers from 1 to 10, gives an array of <code>1</code>’s and <code>0</code>’s that, if you squint your eyes, looks like a graph:</p>

<pre> (⍳10)∘.≤SALES

1 0 1 1 1 1 1 1 1 1 1 1

0 0 1 1 1 1 1 1 1 1 1 1

0 0 1 1 0 1 1 1 1 1 1 0

0 0 0 1 0 1 1 1 1 1 0 0

0 0 0 1 0 1 1 1 1 1 0 0

0 0 0 0 0 1 1 1 1 0 0 0

0 0 0 0 0 1 1 1 1 0 0 0

0 0 0 0 0 0 1 0 1 0 0 0

0 0 0 0 0 0 1 0 1 0 0 0

0 0 0 0 0 0 1 0 1 0 0 0</pre>

<p>You can use <strong>indexing</strong> to change the 0’s and 1’s into blanks and symbols so the data is easier to analyze:</p>

<pre> ' ⎕'[1+(⍳10)∘.≤SALES]

⎕ ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕

⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕

⎕⎕ ⎕⎕⎕⎕⎕⎕

⎕ ⎕⎕⎕⎕⎕

⎕ ⎕⎕⎕⎕⎕

⎕⎕⎕⎕

⎕⎕⎕⎕

⎕ ⎕

⎕ ⎕

⎕ ⎕</pre>

<p>A graph like this is a <strong><em>histogram</em></strong> or a <strong><em>bar chart</em></strong>. Most often, in a histogram you want the stacks to build upward not downward. One of many ways to build upward is to do the comparison with the integers from 10 to 1 instead of 1 to 10:</p>

<pre> ' ⎕'[1+(11−⍳10)∘.≤SALES]

⎕ ⎕

⎕ ⎕

⎕ ⎕

⎕⎕⎕⎕

⎕⎕⎕⎕

⎕ ⎕⎕⎕⎕⎕

⎕ ⎕⎕⎕⎕⎕

⎕⎕ ⎕⎕⎕⎕⎕⎕

⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕

⎕ ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕</pre>

<p>Note: <span class="small-caps">IBM</span>’s <span class="small-caps">APL2</span> Release 3 adds the function <strong>indexing</strong> (<code>⌷</code>) as an alternative form of indexing. For information on this new function, see <a href="appendixF.html">Appendix F</a>.</p>

<h4 id="selecting-items-with-a-mask-replication">Selecting Items with a Mask: Replication<a href="#selecting-items-with-a-mask-replication" class="section-link">§</a></h4>

<p><strong>Indexing</strong> can select zero or more of each item of a vector. If you do not specify the index to an item, <strong>indexing</strong> doesn’t select the item at all. If you specify the index once, the item is selected once. Specify the index twice and you get the item twice; and so forth:</p>

<pre> CV1←'SANDY'

CV1[2 2 3 5 5 5]

AANYYY</pre>

<p>The <span class="small-caps">APL2</span> operator <strong>replicate</strong>—often called <strong>compress</strong>—gives a different way of doing this kind of selection. The left operand is a vector as long as the right argument and indicates how many times to select the corresponding item from the right argument:</p>

<pre> 0 2 1 0 3/CV1

AANYYY</pre>

<p>A left operand of only <code>1</code>s and <code>0</code>s is very useful in selecting a subset of items. For example, if <code>SALARY</code> is a vector of salaries, you can select all salaries greater than 5000 with the following expression:</p>

<pre> SALARY←6500 4200 3700 9200 6700

(SALARY&gt;5000)/SALARY

6500 9200 6700</pre>

<p><code>SALARY&gt;5000</code> evaluates to true (<code>1</code>) or false (<code>0</code>) for each item of salary:</p>

<pre> SALARY&gt;5000

1 0 0 1 1</pre>

<p>Thus, the expression is equivalent to</p>

<pre> 1 0 0 1 1/SALARY

6500 9200 6700</pre>

<p>A vector of <code>1</code>’s and <code>0</code>’s used as the left operand of <strong>replicate</strong> is often called a <em>mask</em>. Here’s an example of a mask generated by Boolean functions that is then applied to a nested array:</p>

<pre> RETAIL←6.95 7.95 12.95

WHAT←'LPS' 'TAPES' 'CDS'

(RETAIL&lt;10) ∧ (RETAIL&gt;7)

0 1 0

((RETAIL&lt;10) ∧ (RETAIL&gt;7))/WHAT

TAPE</pre>

<p>You can use <strong>replicate</strong> to double the quotation marks in a character vector. Remember that to get one quotation mark on input of a character string, you must enter two quotation marks:</p>

<pre> CV2←'DON''T'

CV2

DON'T

⍴CV2

5

CV2='''' &lt;---right argument is a scalar quotation mark

0 0 0 1 0

1+CV2=''''

1 1 1 2 1

(1+CV2='''')/CV2

DON''T

⍴(1+CV2='''')/CV2

6</pre>

<p><strong>Replicate</strong> also applies to higher-rank arrays by the use of an axis specification. The right argument is split along the specified axis, the vector definition of <strong>replicate</strong> is applied, and the pieces are put back together again. When an axis is not written, it defaults to the rightmost axis:</p>

<pre> A← 4 6⍴⍳24

A

1 2 3 4 5 6

7 8 9 10 11 12

13 14 15 16 17 18

19 20 21 22 23 24

1 0 0 0 3 2/A

1 5 5 5 6 6

7 11 11 11 12 12

13 17 17 17 18 18

19 23 23 23 24 24</pre>

<p>Notice that column 1 is selected once, column 5 is selected three times, and column 6 is selected twice.</p>

<p><strong>Replicate</strong> along the first axis selects selects rows of a matrix:</p>

<pre> NAMES←4 4⍴'JOHNJIM EV MIKE'

1 0 1 0/[1] NAMES

JOHN

EV </pre>

<p>You can use the symbol <code>⌿</code> for <strong>replicate</strong>, in which case the axis defaults to the leftmost axis:</p>

<pre> 1 0 1 0⌿NAMES

JOHN

EV </pre>

<p>Note: <strong>replicate</strong> is an operator, not a function. It is the first operator you’ve seen that takes an array as an operand. <strong>Replicate</strong> is the same operator as <strong>reduction</strong>. The name varies according to whether the operand is an array or a function:</p>

<center>

<table>

<tbody>

<tr>

<td style="text-align: right;">array<code>/</code></td>

<td style="text-align: left;">— <strong>replicate</strong></td>

</tr>

<tr>

<td style="text-align: right;">function<code>/</code></td>

<td style="text-align: left;">— <strong>reduction</strong></td>

</tr>

</tbody>

</table>

</center>

<p>In simple cases, you can think of <strong>replicate</strong> as a function. But in expressions with other operators, you must treat <strong>replicate</strong> as an operator. Here is an example:</p>

<pre> 1 0 1/¨ 'ABC' (1 2 3)

AC 1 3</pre>

<p>If you add redundant parentheses, this expression looks like this:</p>

<pre> (1 0 1/)¨ 'ABC' (1 2 3)

AC 1 3</pre>

<p>The operator <code>/</code> applies to its operand <code>1 0 1</code> to produce a derived function, which might be called the <strong>1 0 1-replicate</strong> function. This monadic derived function is then the operand of the <strong>each</strong> operator, which applies it to each item of the argument:</p>

<pre> (1 0 1/'ABC')(1 0 1/1 2 3)

AC 1 3</pre>

<p>Applying two masks to two vectors requires some special thought. If you want to apply two masks to two vectors, you might be tempted to try this:</p>

<pre> (1 0 1)(110)/¨ 'ABC' (1 2 3)

DOMAIN ERROR

(1 0 1)(1 1 0)/¨ 'ABC' (1 2 3)

^ ^</pre>

<p>The expression looks as though it should work, but the operator <code>/</code> applies to the operand <code>(1 0 1)(1 1 0)</code> first, and <strong>replicate</strong> is not defined on a nested left argument. If you want to apply two masks to two vectors, you must write a defined function that does only the replication and then apply that function using <strong>each</strong>. The following is an example:</p>

<pre> ∇Z←L REP R

[1] ⍝ replicate function

[2] Z←L/R

[3] ∇

(1 0 1)(1 1 0) REP¨ 'ABC' (1 2 3)

AC 1 2</pre>

<p><code>REP</code> works where <code>/¨</code> fails because <code>REP</code> is a function and <code>/</code> is an operator.</p>

<h4 id="selecting-items-with-a-mask-expansion">Selecting Items with a Mask: Expansion<a href="#selecting-items-with-a-mask-expansion" class="section-link">§</a></h4>

<p>The <span class="small-caps">APL2</span> operator <strong>expand</strong> (<code>\</code>) takes a Boolean mask as its left operand. The mask specifies a pattern for building the result. There is a one in the mask for each item in the right argument. Ones in the mask identify where items from the right argument are placed in the result. Zeros in the mask identify where the result should be padded with a fill value:</p>

<pre> 1 1 0 1 0 1\1 2 3 4

1 2 0 3 0 4

1 1 0 1 0 1\'ABCD'

AB C D</pre>

<p>When you apply <strong>expand</strong> to a nested array, the result is padded with items that look like the first item but with numbers replaced by zeros and characters replaced by blanks:</p>

<pre> 1 0 1\(2 'A' 3)(19 'B' 21)

2 A 3 0 0 19 B 21

DISPLAY 1 0 1\(2 'A' 3)(19 'B' 21)

.→--------------------------.

| .→----. .→----. .→------. |

| |2 A 3| |0 0| |19 B 21| |

| '+----' '+----' '+------' |

'∊--------------------------'</pre>

<p>Here’s a practical example of <strong>expand</strong>. Given a vector <code>A</code>, insert between each pair of numbers the average of the pair. For example, with the given array <code>A</code> the desired result <code>NEWA</code> is shown here:</p>

<pre> A←10 12 15 17 16 8

NEWA←10 11 12 13.5 15 16 17 16.5 16 12 8</pre>

<p>Solving this problem mainly requires <strong>n-wise reduction</strong> and <strong>expand</strong>. You can easily compute the average of adjacent numbers using <strong>n-wise reduction</strong>:</p>

<pre> AV←(2+/A)×+.5

AV

11 13.5 16 16.5 12</pre>

<p><strong>Expand</strong> with the appropriate mask puts the original numbers into their proper positions in the longer result:</p>

<pre> 1 0 1 0 1 0 1 0 1 0 1\A

10 0 12 0 15 0 17 0 16 0 8</pre>

<p>If you don’t know the shape of <code>A</code>, you can compute the mask instead:</p>

<pre> M←(¯1+2×⍴A)⍴1 0

M

1 0 1 0 1 0 1 0 1 0 1

M\A

10 0 12 0 15 0 17 0 16 0 8</pre>

<p>The <strong>not</strong> of the mask puts the average values in their proper place:</p>

<pre> (∼M)\AV

0 11 0 13.5 0 16 0 16.5 0 12 0</pre>

<p>The desired result is achieved by adding the two parts together:</p>

<pre> (M\A)+(∼M)\AV

10 11 12 13.5 15 16 17 16.5 16 12 8</pre>

<p>When you apply <strong>expand</strong> to a higher-rank array, an axis may be specified. If no axis is specified, <span class="small-caps">APL2</span> assumes the rightmost axis. The right argument is split into an array of vectors along the indicated axis, and the vector definition of <strong>expand</strong> is applied to each vector. Here is an example:</p>

<pre> CH←3 5⍴'ABCDEFGHIJKLMNO'

CH

ABCDE

FGHIJ

KLMNO

1 1 0 0 1 0 1 1\CH

AB C DE

FG H IJ

KL M NO

1 1 0 1\[1]CH

ABCDE

FGHIJ

KLMNO</pre>

<p>The symbol <code>⍀</code> may be used to signify expansion along the first axis. Note: Like <strong>replicate</strong>, <strong>expand</strong> is an operator, not a function.</p>

<h4 id="without">Without<a href="#without" class="section-link">§</a></h4>

<p>It is possible to select items from a vector by specifying the items not wanted. The function <strong>without</strong> (<code>∼</code>) returns its left argument with any occurrences of items from the right argument deleted:</p>

<pre> 'THIS AND THAT'∼'HT'

IS AND A

'BILLY JOE ' ∼ ' '

BILLYJOE</pre>

<p>The example shows a quick way to remove blanks from a character vector. These blanks could arise because of the use of an <strong>enclose</strong>, as in this example:</p>

<pre> NAMES←4 4⍴'JOHNJIM EV MIKE'

⊂[2] NAMES

JOHN JIM EV MIKE</pre>

<p>Because these vectors came from a 4-by-4 matrix, each is a vector of length 4 and some have trailing blanks. The following expression deletes the blanks from each item:</p>

<pre> (⊂[2]NAMES)∼¨' '

JOHN JIM EV MIKE</pre>

<p>Finally, <strong>without</strong> can compute the intersection of two arrays (that is, the items that occur in both arrays) as follows:</p>

<pre>X∼X∼Y</pre>

<p>Here is an example:</p>

<pre> 1 3 5 7 9 ∼ 1 3 5 7 9 ∼ 3 7 11

3 7</pre>

<h4 id="selective-assignment">Selective Assignment<a href="#selective-assignment" class="section-link">§</a></h4>

<p><span class="small-caps">APL2</span> supplies a variety of ways to organize and extract parts of an array for those situations when you don’t want to operate on the entire array. These functions include <strong>reshape</strong>, <strong>ravel</strong>, <strong>enclose</strong>, <strong>take</strong>, <strong>drop</strong>, <strong>pick</strong>, and <strong>indexing</strong>. They can be used in combination to express a wide variety of selections. Here is an expression that selects one corner of a matrix that is an item in a nested array:</p>

<pre> SA←10 'ABC' (3 3⍴⍳9) 20 (5 6)

DISPLAY SA

.→--------------------------.

| .→--. .→----. .→--. |

| 10 |ABC| ↓1 2 3| 20 |5 6| |

| '---' |4 5 6| '∼--' |

| |7 8 9| |

| '∼----' |

'∊--------------------------'

,2 2↑3⊃SA

1 2 4 5</pre>

<p>You can write any expression that results in a selection of all or part of an array in parentheses on the left of an assignment arrow. <span class="small-caps">APL2</span> replaces the values selected by that expression with values from the array on the right of the arrow:</p>

<pre> (,2 2↑3⊃SA)←'WXYZ'

DISPLAY SA

.→--------------------------.

| .→--. .→----. .→--. |

| 10 |ABC| ↓W X 3| 20 |5 6| |

| '---' |Y Z 6| '∼--' |

| |7 8 9| |

| '+----' |

'∊--------------------------'</pre>

<p>If the preceding example does not work on your system, your implementation may not support selective assignment.</p>

<p>An assignment with a selection expression on the left is a <em>selective assignment</em>. The variable whose value is altered is the one whose name appears at the right end of the selection expression (if you ignore square brackets used for <strong>indexing</strong>).</p>

<p>In these expressions, <code>SA</code> is the only variable whose value is altered:</p>

<pre> (2↑SA)←(10 20)(⍳3)

(SA[4])←⊂2.3 3.4

((5⊃SA)[2])←'S'

((⍳0)⊃SA)←0</pre>

<p>As with any assignment, the explicit result of a selective assignment is the array on the right and does not print. It is, however, available for further computation:</p>

<pre> 1+(2↑SA)←(10 20)(⍳3)

11 21 2 3 4 </pre>

<p>There are three guidelines to help you evaluate an indexed assignment. These guidelines work if the selection expression does not contain any functions that add depth (like <strong>enclose</strong>), and does not contain operators (like <strong>each</strong>). You should apply the first guideline that fits the expression you are analyzing. Consult the documentation that comes with your system for a more complete description.</p>

<ol>

<li><p>If the leftmost function in the selection expression is <strong>first</strong> or <strong>pick</strong>, the item selected is replaced by the array on the right of the assignment arrow:</p>

<pre> W←'LPS' 'TAPES' 'DISKS'

(3 4⊃W)←'C'

W

LPS TAPES DISCS

SA←10 'ABC' (3 3⍴⍳9) 20 (5 6)

(↑2↓SA)←¯1 ¯2

DISPLAY SA

.→--------------------------.

| .→--. .→----. .→--. |

| 10 |ABC| |¯1 ¯2| 20 |5 6| |

| '---' '∼----' '∼--' |

'∊--------------------------'

SA←10 'ABC' (3 3⍴⍳9) 20 (5 6)

(3 (2 2)⊃SA)←'MID'

DISPLAY SA

.→--------------------------------.

| .→--. .→----------. .→--. |

| 10 |ABC| ↓ 1 2 3 | 20 |5 6| |

| '---' | | '∼--' |

| | .→--. | |

| | 4 |MID| 6 | |

| | '---' | |

| | | |

| | 7 8 9 | |

| | | |

| '∼----------' |

'∊--------------------------------'

((⍳0)⊃SA)←0

SA

0</pre>

<p>This last selective assignment of <code>SA</code> is like an ordinary assignment (<code>SA←0</code>) except the variable <code>SA</code> must already have a value (even though that value is ignored).</p></li>

<li><p>If the array on the right of the assignment is a scalar, it replaces each item selected by the selection expression:</p>

<pre> SA←10 'ABC' (3 3⍴⍳9) 20 (5 6)

SA[1 4 5]←0

DISPLAY SA

.→--------------------.

| .→--. .→----. |

| 0 |ABC| ↓1 2 3| 0 0 |

| '---' |4 5 6| |

| |7 8 9| |

| '∼----' |

'∊--------------------'

(2 2↑3⊃SA)←0

DISPLAY SA

.→--------------------.

| .→--. .→----. |

| 0 |ABC| ↓0 0 3| 0 0 |

| '---' |0 0 6| |

| |7 8 9| |

| '∼----' |

'∊--------------------'</pre>

<p>Neither the rank nor the shape of the selected array changes.</p></li>

<li><p>Each value from the array selected is replaced by the corresponding value from the array on the right of the assignment arrow:</p>

<pre> SA←10 'ABC' (3 3⍴⍳9) 20 (5 6)

SA[1 5]←'ONE' 'FIVE'

DISPLAY SA

.→------------------------------.

| .→--. .→--. .→----. .→---. |

| |ONE| |ABC| ↓1 2 3| 20 |FIVE| |

| '---' '---' |4 5 6| '----' |

| |7 8 9| |

| '∼----' |

'∊------------------------------'

(,2⊃SA)←⍳3

DISPLAY SA

.→--------------------------------.

| .→--. .→----. .→----. .→---. |

| |ONE| |1 2 3| ↓1 2 3| 20 |FIVE| |

| '∼--' '∼----' |4 5 6| '∼---' |

| |7 8 9| |

| '∼----' |

'∊--------------------------------'</pre>

<p>Neither the rank nor the shape of the selected array changes:</p>

<ul>

<li>The array selected and the array on the right must have the same rank or <span class="small-caps">APL2</span> produces a <code>RANK ERROR</code>.</li>

<li>The array selected and the array on the right must have the same shape or <span class="small-caps">APL2</span> produces a <code>LENGTH ERROR</code>.</li>

</ul></li>

</ol>

<p>Note on scalar extension and conformability: <span class="small-caps">APL2</span> relaxes the conformability rules for selective assignment by ignoring <code>1</code>’s in shape vectors. If you select a subset whose shape is <code>1 5</code>, you may replace the subset by replacement values of shape <code>5 1</code>. Ignoring <code>1</code>’s, each array has shape <code>5</code>. In particular, if the array on the right contains only one item, it is treated as a scalar and extended no matter how many <code>1</code>’s are in its shape.</p>

<p>While any expression that does a selection from an array is permitted on the left of an assignment arrow, implementations may not support them all. Consult the documentation that comes with your system or experiment to see which selections are supported.</p>

<h4 id="exercises-for-section-6.2">Exercises for Section 6.2<sup class="answers-note">[<a href="answers.html#section-6.2-selecting-subsets-of-arrays">Answers</a>]</sup><a href="#exercises-for-section-6.2" class="section-link">§</a></h4>

<ol>

<li><p>Given the matrix:</p>

<pre> SA←5 10⍴⍳50</pre>

<p>Evaluate the following expressions in order and show the value of <code>SA</code> after each is complete. If any expression results in an error, say what causes the error:</p>

<ol type="a">

<li><code>SA[2;10]←'X'</code></li>

<li><code>SA[3;10]←'XYZ'</code></li>

<li><code>SA[4;10]←⊂'XYZ'</code></li>

<li><code>SA[;3]←0</code></li>

<li><code>SA[;]←' '</code></li>

<li><code>(0 1 0 1 0⌿SA)←2 10⍴−⍳20</code></li>

</ol></li>

<li><p>Given the vector:</p>

<pre> TM←(2 2⍴'ABC' 'DE' (⍳¨⍳2) 10) 'ABC'</pre>

<p>What is the difference between <code>TM[1]</code> and <code>↑TM</code>?</p></li>

<li><p>Write an expression to replace all <code>0</code>’s in a numeric matrix with the character vector <code>N/A</code>. Here is an example:</p>

<pre> 1 0 becomes 1 N/A

0 5 N/A 5</pre></li>

<li><p>A manufacturing company has just issued a list of serial numbers of their product for recall. These numbers are in the vector <code>RLIST</code>. Write an expression to list which of the company’s products in your inventory vector <code>INVENTORY</code> are on the recall list.</p></li>

<li><p>Given simple numeric vector <code>V</code>, write an expression to replace all the numbers in <code>V</code> that are greater than 10 with the character <code>X</code>, leaving the other items alone.</p></li>

<li><p>Given two simple arrays <code>M</code> and <code>N</code> with the same rank and shape, write an expression to replace by a blank all items of <code>N</code> different from the corresponding items in <code>M</code>.</p></li>

<li><p>Explain why the following expression does not expand each item of <code>B</code> using the corresponding mask from <code>M</code>:</p>

<pre> M←(1 1 0 1)(0 1 0 1)

B←'ABC' 'DE'

M\¨B</pre></li>

<li><p>Evaluate the following expressions. For each, determine its value and its depth:</p>

<ol type="a">

<li><code>'BYEBYE' ∼ 'BY'</code></li>

<li><code>'BY' ∼ 'BYEBYE'</code></li>

<li><code>'BYEBYE' ∼ 'BYEBYE' ∼ 'BY'</code></li>

<li><code>'BYEBYE' ∼ ⊂'BY'</code></li>

<li><code>(⊂'BYEBYE') ∼ 'BY'</code></li>

<li><code>'CAB' 'DAD' ∼ 'AB'</code></li>

<li><code>'CAB' 'DAD' ∼¨ 'AB'</code></li>

<li><code>'CAB' 'DAD' ∼ ⊂'AB'</code></li>

<li><code>'CAB' 'DAD' ∼¨ ⊂'AB'</code></li>

</ol></li>

<li><p>Evaluate each of the following expressions. For each, state both the result and the depth:</p>

<ol type="a">

<li><code>1 0 1/'APL’</code></li>

<li><code>1 0 1/⊂'APL'</code></li>

<li><code>1 2 3/'APL'</code></li>

<li><code>1 2 3/⊂'APL'</code></li>

<li><code>1 0 ¯2 3/'APL'</code></li>

<li><code>1 0 ¯2 3/5 8 9</code></li>

<li><code>1 0 1/'A' 23 'C'</code></li>

<li><code>1 0 2/'A' 23 'C'</code></li>

<li><code>1 2 0/'A' 23 'C'</code></li>

</ol></li>

<li><p>State the value of each of the following expressions:</p>

<ol type="a">

<li><code>1 0 0 1 1 \ 'APL'</code></li>

<li><code>1 0 0 1 1 \ 10 20 30</code></li>

<li><code>((2×⍴V)⍴1 0) \ V←'ABCDEF'</code></li>

<li><code>1 1 0 1 0 1 \ 3 4⍴'ABCD'</code></li>

<li><code>1 0 0 1 0 1 ⍀ 3 4⍴⍳4</code></li>

<li><code>0 1 0 1 0 1\ 'AB'</code> (Why?)</li>

<li><code>0\0/ 3 4 5</code></li>

<li><code>0\0/(3 4) 5</code></li>

<li><code>0\0/ ('A' 4) 5</code></li>

<li><code>0\0/ (4 'A') 5</code></li>

<li><code>1 0 1 0 1 \ 'ABC' (⍳4) ('A' 4)</code></li>

<li><code>1 0 1 0 1 \ (⍳4) 'ABC' ('A' 4)</code></li>

<li><code>1 0 1 0 1 \ ('A' 4) (⍳4) 'ABC'</code></li>

<li><code>1 0 1 0 1 \ (4 'A') (⍳4) 'ABC'</code></li>

</ol></li>

<li><p>Let <code>M1</code>, <code>M2</code>, <code>M3</code> be three rank-2 arrays having the same shape.</p></li>

</ol>

<ol type="a">

<li>For a given mask <code>V</code> where <code>(⍴V)≡ ¯1↑⍴M</code>, write an expression that uses <code>V</code> to select the same columns from each of the matrices.</li>

<li>Given three masks <code>V1</code>, <code>V2</code>, <code>V3</code> and matrices <code>M1</code>, <code>M2</code>, and <code>M3</code>, determine how to use each mask to compress the corresponding matrix. (You will need to create a simple defined function first and then use it in an expression.)</li>

<li>Given three masks <code>V1</code>, <code>V2</code>, <code>V3</code>, apply them each to the matrix <code>M</code>, giving three sets of answers. (Note: Use the function defined in part b.)</li>

</ol>

<ol start="12">

<li><p>If <code>M</code> is a rank-2 array, the following expression replaces all the items of <code>M</code> by <code>12</code>:</p>

<pre> M[;]←12</pre>

<p>Write an expression to replace all the items in an array of unknown rank by <code>12</code>.</p></li>

<li><p>Write an expression to replace all simple scalars in a nested array by <code>21</code>.</p></li>

</ol>

<h3 id="section-6.3-searching-and-sorting">Section 6.3 — Searching and Sorting<a href="#section-6.3-searching-and-sorting" class="section-link">§</a></h3>

<p>To aid in searching for particular items in an array and sorting items, <span class="small-caps">APL2</span> provides these functions:</p>

<ul>

<li><strong>index of</strong></li>

<li><strong>membership</strong></li>

<li><strong>find</strong></li>

<li><strong>grade up and grade down</strong></li>

<li><strong>reverse</strong></li>

<li><strong>rotate</strong></li>

<li><strong>transpose</strong></li>

</ul>

<h4 id="index-of">Index Of<a href="#index-of" class="section-link">§</a></h4>

<p><strong>Index of</strong> (<code>⍳</code>) is a function that searches a vector left argument for occurrences of items from the right argument. You can search for many items at one time, but you can search only in a vector. The following is an example:</p>

<pre> LI← 20 40 60 80 40

LI⍳80 40

4 2</pre>

<p>The result always has the same shape as the right argument. Each position in the result is the index position of the first place in the left argument where the item from the right argument is found. Thus, <code>80</code> is found at position 4 in <code>LI</code> and <code>40</code> is found in position 2. The fact that <code>40</code> is also found at position 5 is not reported.</p>

<p>If an item searched for is not found, a number one greater than the length of the left argument is returned:</p>

<pre> LI⍳100

6</pre>

<p>A program can check if a given value is found in another vector by comparing for the number one greater than the length of the vector:</p>

<pre> (⍴LI)&lt;LI⍳100

1</pre>

<p>This expression is true (<code>1</code>) only when the result of <strong>index of</strong> is the “not found” value. See the program <code>LOOKUP</code> in the section “More About Conditional Branching” in <a href="chapter7.html">Chapter 7</a> for an example of a program that uses this test.</p>

<p>If the left argument is a nested vector, an item from the right is found if it matches an item on the left:</p>

<pre> WHAT←'LPS' 'TAPES' 'CDS'

WHAT ⍳ 'CDS' 'GUITARS'

3 4</pre>

<p>Here <code>'CDS'</code> is found at position 3, but <code>'GUITARS'</code> is not found at all. Suppose you just want to search for the index of <code>'CDS'</code>. You might think that the following expression would find it:</p>

<pre> WHAT⍳'CDS'

4 4 4</pre>

<p>This is clearly not the answer wanted. Can you figure out why you got the answer <code>4 4</code>? The right argument is a three-item vector containing the characters <code>'C'</code>, <code>'D'</code>, and <code>S</code>, so you get three answers. Remember that vector notation only works for vectors of length two or longer and here you want a right argument with only one item—the vector <code>'CDS'</code>. If you want to search for one item, you must use the function <strong>enclose</strong> (<code>⊂</code>) to make the vector <code>'CDS'</code> into a one-item array:</p>

<pre> WHAT⍳⊂'CDS'

3</pre>

<p>Now <strong>index of</strong> finds the three-item vector <code>'CDS'</code> at position 3.</p>

<p>You can use <strong>index of</strong> on character arguments as a way to convert characters to numbers:</p>

<pre> ALPH←'ABCDEFGHIJKLMNOPQRSTUVWXYZ '

ALPH⍳'SECRET MESSAGE'

19 5 3 18 5 20 27 13 5 19 19 1 7 5</pre>

<p>These numbers are like a code hiding your message. Of course, your code is easy to break by using <strong>indexing</strong>:</p>

<pre> MESSAGE←ALPH⍳'SECRET MESSAGE'

ALPH[MESSAGE]

SECRET MESSAGE</pre>

<p>This example shows that, in some respects, <strong>indexing</strong> is the inverse of <strong>index of</strong>.</p>

<p>You can use <strong>index of</strong> to select the unique items from a vector. Suppose you have the following vector:</p>

<pre> NV←'JIM' 'JOHN' 'JIM' 'DIETER' 'PIER' 'JIM'</pre>

<p><strong>Index of</strong> will find only the first occurrence of each name:</p>

<pre> NV⍳NV

1 2 1 4 5 1</pre>

<p>Comparing this with the first six integers gives a mask for selecting each name only once:</p>

<pre> (NV⍳NV)=⍳⍴NV

1 1 0 1 1 0

((NV⍳NV)=⍳⍴NV)/NV

JIM JOHN DIETER PIER</pre>

<h4 id="membership">Membership<a href="#membership" class="section-link">§</a></h4>

<p><strong>Index of</strong> tells you the index of some given item in a vector. If you want to know only whether an item occurs (as opposed to where it occurs), you can use the function <strong>membership</strong> (<code>∊</code>). <strong>Membership</strong> gives a <code>1</code> or <code>0</code>, depending on whether each item of the left argument is (<code>1</code>) or is not (<code>0</code>) found in the right argument:</p>

<pre> LI←20 40 60 80 40

100 40∊LI

0 1</pre>

<p>Notice that the array in .which the search takes place is the right argument (just the opposite of <strong>index of</strong>) and can be any array, not just a vector. In this way, <strong>membership</strong> is similar to (but not the same as) the membership function found in set theory. In the example, <code>100</code> is not found (giving <code>0</code>) but <code>40</code> is found (giving <code>1</code>).</p>

<p>The following examples illustrate a situation where you might want to know if an item exists but not care about its position:</p>

<pre> (⊂'CDS')∊WHAT

1

(⊂'GUITARS')∊WHAT

0</pre>

<p>Here, <strong>membership</strong> is being used to determine whether the character string in the left argument represents a product stocked by the store. If the answer is <strong>yes</strong>, then you may proceed to look up other information about the product. If the answer is <strong>no</strong>, there is no point in looking further.</p>

<p>An <strong>inner product</strong> using <strong>addition</strong> and <strong>membership</strong> produces a count of the occurrences from the left argument that can be found in the right argument:</p>

<pre> I←3 10⍴'1988/05/0413:00:00:1A,B,C,D,E '

I

1988/05/04

13:00:00:1

A,B,C,D,E

⍴I

3 10

⍴'.,:;/\'

6

I +.∊'.,:;/\'

2 3 4

⍴I +.∊'.,:;/\'

3</pre>

<h4 id="find">Find<a href="#find" class="section-link">§</a></h4>

<p><strong>Find</strong> (<code>⍷</code>) is like <strong>membership</strong> except that <strong>find</strong> looks for the whole left argument and you get, for the result, an indication of everywhere that the left argument occurs. Although <strong>find</strong> works for any kind of data, it is most useful (and easiest to demonstrate) on character strings:</p>

<pre> 'ABC'⍷'ABABCDABCEAB'

0 0 1 0 0 0 1 0 0 0 0 0</pre>

<p>This result is the same length as the right argument and has a <code>1</code> where the left character string begins. The number of occurrences of the left in the right is:</p>

<pre> +/'ABC'⍷'ABABCDABCEAB'

2</pre>

<p>Here’s a character vector with some redundant blanks:</p>

<pre> PHRASE←'NOW IS THE TIME'</pre>

<p>You can use <strong>find</strong> to delete the duplicate blanks from <code>PHRASE</code> by looking for two blanks:</p>

<pre> ' '⍷PHRASE

0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0</pre>

<p>This result has a <code>1</code> for each blank to be discarded. Interchanging the <code>1</code>’s and <code>0</code>’s (with <strong>not</strong>) gives the correct mask for <strong>replicate</strong>.</p>

<pre> (~' '⍷PHRASE)/PHRASE

NOW IS THE TIME</pre>

<h4 id="grade-up-and-grade-down">Grade Up and Grade Down<a href="#grade-up-and-grade-down" class="section-link">§</a></h4>

<p>In <a href="chapter5.html">Chapter 5</a>, you saw <strong>catenate with axis</strong> used to build a matrix of possible purchases:</p>

<pre> PURCHASES

LPS .9 6.95

TAPES .9 7.95

CDS 1 12.95

VIDEODISCS 1 19</pre>

<p>It happens that the retail cost is ordered from least to most expensive. This is an accidental ordering but could be useful. Suppose that you add a fifth row to the matrix:</p>

<pre> PURCHASES←PURCHASES,[1]'VIDEOTAPES' 1 13.50

PURCHASES

LPS .9 6.95

TAPES .9 7.95

CDS 1 12.95

VIDEODISCS 1 19

VIDEOTAPES 1 13.5</pre>

<p>Now the price column is no longer in order. <span class="small-caps">APL2</span> has two functions that order data: <strong>grade up</strong> (<code>⍋</code>), to arrange data in increasing order, and <strong>grade down</strong> (<code>⍒</code>), to arrange data in decreasing order. These functions work on vectors of numbers. Here are the functions applied to the price column:</p>

<pre> PURCHASES[;3]

6.95 7.95 12.95 19 13.5

⍋PURCHASES[;3]

1 2 3 5 4

⍒PURCHASES[;3]

4 5 3 2 1</pre>

<p>As you can see, these functions do not produce their argument in sorted order. You might have expected to see <strong>grade up</strong> return an answer of <code>6.95 7.95 12.95 13.5 19</code>. Instead, you get a vector of small integers. In each example, the answer is a rearrangement of the integers from <code>1</code> to <code>5</code>. These integers are indices that reflect the requested ordering. For example, in <strong>grade up</strong>, the answer is <code>1 2 3 5 4</code>. These indices mean that to get an increasing vector, you select the first and second items, then the third item, and then the fifth and fourth items, giving the vector sorted in ascending order: <code>6.95 7.95 12.95. 13.5 19</code>. <strong>Indexing</strong> accomplishes this selection:</p>

<pre> T←PURCHASES[;3]

T[⍋T]

6.95 7.95 12.95 13.5 19

T[⍒T]

19 13.5 12.95 7.95 6.95</pre>

<p>Why is this extra step required? Why shouldn’t the functions just give you the ordered data directly? The answer is that, in practice, you want to rearrange a whole collection of data based on the ordering of one part of the data. The prices sorted in order are not very useful if you can’t identify what product they are associated with. Thus, you want to rearrange the whole matrix based on the order of the prices:</p>

<pre> PURCHASES[⍋PURCHASES[;3];]

LPS .9 6.95

TAPES .9 7.95

CDS 1 12.95

VIDEOTAPES 1 13.5

VIDEODISCS 1 19</pre>

<p>This example shows the rows of <code>PURCHASES</code> rearranged based on the order in the third column.</p>

<p>The grade functions in their dyadic form apply to matrices of character data. The following selects the product names and constructs a matrix from them:</p>

<pre> PNAMES←⊃PURCHASES[;1]

PNAMES

LPS

TAPES

CDS

VIDEODISCS

VIDEOTAPES</pre>

<p>Before the rows of this matrix can be put in order, you have to decide what you mean by the order of characters. To English-speaking people, the order A to Z looks like a good choice. But there are lots of alphabets in the world that use characters not in this set. Even in the roman alphabet, you have to decide where lowercase letters belong. Is a lowercase “a” greater or less than an uppercase “Z”? Whatever you decide, you should code your decision as the left argument of the grade functions. The next three examples show left arguments:</p>

<pre> CS1←' ABCDEFGHIJKLMNOPQRSTUVWXYZ'</pre>

<p>This sample argument, where all roman letters are written, puts capitalized words first and in order.</p>

<pre> CS2←' AaBbCcDdEe ... YyZz'</pre>

<p><code>CS2</code> puts words starting with <code>A</code> first, followed by words starting with <code>a</code>.</p>

<pre> CS3←2 27⍴' ABCDE ... XYZ abcde ... xyz'</pre>

<p><code>CS3</code> as a left argument orders the rows of a character matrix and ignores capitalization. In a matrix left argument to the grade functions, characters in the same column are treated as though they are the same character. Because the product names are all in uppercase letters, any of the three preceding arrays as left argument gives the same result:</p>

<pre> CS3⍋PNAMES

3 1 2 4 5</pre>

<p>Again, this result is an index vector that rearranges the data.</p>

<pre> PNAMES[CS3⍋PNAMES;]

CDS

LPS

TAPES

VIDEODISCS

VIDEOTAPES

PURCHASES[CS3⍋PNAMES;] &lt;---This vector rearranges

CDS 1 12.95 the whole table

LPS .9 6.95

TAPES .9 7.95

VIDEODISCS 1 19

VIDEOTAPES 1 13.5</pre>

<p>Double <strong>grade up</strong> has some surprising uses. For example, suppose you have these three collections of data:</p>

<pre> A←'XYZ'

B← 123

C← 2.1 2.2 2.3</pre>

<p>You want to merge these data collections into the following vector:</p>

<pre> 'X' 1 'Y' 2.1 'Z' 2.2 2 2.3 3</pre>

<p>Here’s a picture of the mapping. The numbers written under the desired answer indicate which variable the corresponding item came from: 1 for <code>A</code>, 2 for <code>B</code>, and 3 for <code>C</code>:</p>

<center>

<img src="images/mapping_grade.png">

</center>

<p>Applying a double <strong>grade up</strong> to the vector of integers in the illustration generates indices that will merge the three vectors in the desired manner:</p>

<pre> MV←1 2 1 3 1 3 2 3 2

⍋⍋MV

1 4 2 7 3 8 5 9 6

(A,B,C)[⍋⍋MV]

X 1 Y 2.1 Z 2.2 2 2.3 3</pre>

<h4 id="reverse">Reverse<a href="#reverse" class="section-link">§</a></h4>

<p>Suppose you have a vector and would like to turn it around so the first item is last and the last item is first. Given a four-item vector, you could index with <code>4 3 2 1</code>:</p>

<pre> V←'POTS'

V[4 3 2 1]

STOP</pre>

<p>If you don’t know the length of the vector to be reversed in advance, you could compute the indices in many ways:</p>

<pre> V[1+(⍴V)−⍳⍴V]

STOP

V[⍒⍳⍴V]

STOP</pre>

<p>The function <strong>reverse</strong> (<code>⌽</code>) turns the items around in one step:</p>

<pre> ⌽V

STOP</pre>

<p>On higher-rank arguments, <strong>reverse with axis</strong> applies. For the rightmost axis, you may elide the axis specification:</p>

<pre> A←4 6⍴⍳24

A

1 2 3 4 5 6

7 8 9 10 11 12

13 14 15 16 17 18

19 20 21 22 23 24

⌽[1]A

19 20 21 22 23 24

13 14 15 16 17 18

7 8 9 10 11 12

1 2 3 4 5 6

⌽A

6 5 4 3 2 1

12 11 10 9 8 7

18 17 16 15 14 13

24 23 22 21 20 19</pre>

<p><code>⊖</code> is an alternate symbol for <strong>reverse along the first axis</strong>:</p>

<pre> ⊖A

18 20 21 22 23 24

13 14 15 16 17 18

7 8 9 10 11 12

1 2 3 4 5 6</pre>

<h4 id="rotate">Rotate<a href="#rotate" class="section-link">§</a></h4>

<p>The function <strong>rotate</strong> (<code>⌽</code>) shifts the items of a vector by removing items from one side of the vector and reattaching them to the other end. Here is an example:</p>

<pre> PHRASE←'NOW IS THE TIME'

2⌽PHRASE

W IS THE TIMENO</pre>

<p>The left argument gives the number of items for the shift. The name of the function is <strong>rotate</strong> because the items moved out of the left end reappear on the right end.</p>

<p>A negative left argument causes a shift to the right:</p>

<pre> ¯2⌽PHRASE

MENOW IS THE TI</pre>

<p>The character vector <code>PHRASE</code> used in these examples has some extra blanks in it. Earlier, you saw an expression using <strong>find</strong> that deletes duplicate blanks. Here’s another way to do the same thing, using <strong>rotate</strong>:</p>

<pre> P←' '≠PHRASE

P

1 1 1 0 1 1 0 0 1 1 1 0 0 0 1 1 1 1

P ∨ 1⌽P

1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1

(P∨1⌽P)/PHRASE

NOW IS THE TIME</pre>

<p>This selects the non-blank characters and blanks immediately to the left of a non-blank character.</p>

<p>On higher-rank arguments, <strong>rotate with axis</strong> applies. For the rightmost axis you may elide the axis specification. The right argument is split into vectors along the specified axis. If the left argument is a scalar, each vector is rotated that much:</p>

<pre> 1⌽A

2 3 4 5 6 1

8 9 10 11 12 7

14 15 16 17 18 13

20 21 22 23 24 19

1⌽[1]A

7 8 9 10 11 12

13 14 15 16 17 18

19 20 21 22 23 24

1 2 3 4 5 6</pre>

<p>The symbol <code>⊖</code> is <strong>rotate along the first axis</strong>:</p>

<pre> 1⊖A

7 8 9 10 11 12

13 14 15 16 17 18

19 20 21 22 23 24

1 2 3 4 5 6</pre>

<p>You may specify a different rotation amount for each of the vectors in an array. If the left argument is a matrix of rank one less than the right argument, then each vector is rotated by the number corresponding to the vector in the split right argument:</p>

<pre> ¯1 0 1 2⌽A

6 1 2 3 4 5

7 8 9 10 11 12

14 15 16 17 18 13

21 22 23 24 19 20</pre>

<h4 id="transpose">Transpose<a href="#transpose" class="section-link">§</a></h4>

<p>The monadic <strong>transpose</strong> function rearranges an array so that its shape is reversed. In a matrix, <strong>transpose</strong> turns rows into columns and columns into rows.</p>

<pre> AC←3 4⍴'ABCDEFGHIJKL'

AC

ABCD

EFGH

IJKL

⍉AC

AEI

BFJ

CGK

DHL

⍴⍉AC

4 3</pre>

<p>The following identity describes the shape of the result of <strong>transpose</strong>:</p>

<pre> ⍴⍉R &lt;--&gt; ⌽⍴R</pre>

<p>The dyadic <strong>transpose</strong> function rearranges its argument and selects a subset of it. The left argument is a list of integers which indicate where in the result the corresponding axis of the right argument should be placed. Here is an example:</p>

<pre> T←2 4 3⍴⍳30

T

1 2 3

4 5 6

7 8 9

10 11 12

13 14 15

16 17 18

19 20 21

22 23 24

1 3 2⍉T

1 4 7 10

2 5 8 11

3 6 9 12

13 16 19 22

14 17 20 23

15 18 21 24

⍴1 3 2⍉T

2 3 4</pre>

<p>The following picture shows how to predict the shape of dyadic <strong>transpose</strong>—use the left argument to map the argument shape to the result shape:</p>

<center>

<img src="images/dyadic_transpose.png">

</center>

<p>When a number is repeated in the left argument, more than one axis from the argument is mapped to the same axis in the result, with the result length being the minimum of the mapped shapes. Here’s an example with a matrix argument:</p>

<pre> AC←3 4⍴'ABCDEFGHIJKL'

AC

ABCD

EFGH

IJKL

1 1⍉AC

AFK</pre>

<p>Here is a picture of how the result shape is computed:</p>

<center>

<img src="images/dyadic_transpose_shape.png">

</center>

<p>The values selected by this transpose are those where the row index matches the column index: row 1, column 1; row 2, column 2; and row 3, column 3. Now you see why the result shape is the minimum of the axes’ lengths. It is not possible to select row 4, column 4 because there are only three rows.</p>

<p>More general transposes on higher-rank arrays are computed the same way.</p>

<p>The symbol for <strong>transpose</strong> looks a lot like the two symbols used for reverse: a circle and a straight line. If you apply any of these three functions to a 3-by-3 matrix, the line tells you which items do not move:</p>

<pre> X←3 3⍴⍳9

X

1 2 3

4 5 6

7 8 9

(⌽X)(⊖X)(⍉X)

3 2 1 7 8 9 1 4 7

6 5 4 4 5 6 2 5 8

9 8 7 1 2 3 3 6 9

(⊂X)=(⌽X)(⊖X)(⍉X)

0 1 0 0 0 0 1 0 0

0 1 0 1 1 1 0 1 0

0 1 0 0 0 0 0 0 1</pre>

<h4 id="exercises-for-section-6.3">Exercises for Section 6.3<sup class="answers-note">[<a href="answers.html#section-6.3-searching-and-sorting">Answers</a>]</sup><a href="#exercises-for-section-6.3" class="section-link">§</a></h4>

<ol>

<li><p>Write an expression that produces an array having the same shape and depth as array <code>A</code> but filled with 0’s except where <code>A</code> has single digit numbers (that is, between <code>¯9</code> and <code>9</code>) for <code>A</code> as follows:</p>

<ol type="a">

<li>Simple numeric.</li>

<li>Simple but with a mixture of numbers and characters.</li>

</ol></li>

<li><p>Write an expression that selects all non-zero numbers from a nested numeric array.</p></li>

<li><p>Select every item from the array <code>H</code> which is not the character string <code>N/A</code>.</p></li>

<li><p>Given simple array <code>A</code> which contains numbers and the character string <code>N/A</code>, write an expression to replace all the numbers by the number <code>100</code>.</p></li>

<li><p>Given simple array <code>A</code> which contains numbers and the character string <code>N/A</code>, write an expression to replace each number by <code>100</code> times that number.</p></li>

<li><p>Today many cash registers not only print out the cost of each item but also the name of the item. To do this, the system has a <code>STOCK</code> database. Suppose each entry in this database is a vector of three-item vectors. Each three-item vector looks like this: &gt; (inventory number) (product name) (product cost)</p>

<p>For example, here is a specification of the first three items in <code>STOCK</code>:</p>

<pre> CEREAL ←(112 'ALPHABYTE' 1.89)

BREAD←(213 'SO_SOFT BREAD' 1.09)

SOAP←(456 'LIFE GIRL SOAP' 1.75)

STOCK← CEREAL BREAD SOAP</pre>

<p>Define a function that will accept a vector of inventory numbers and the name of the stock database, and will produce a matrix listing of the item names and prices that match the inventory numbers.</p></li>

<li><p>You saw the use of <strong>index of</strong> to delete duplicate items from a vector. Write an expression to delete duplicate rows from a matrix.</p></li>

<li><p>Given the following matrix:</p>

<pre> M←(⍳4)∘.≥⍳4

1 0 0 0

1 1 0 0

1 1 1 0

1 1 1 1</pre>

<p>Use <strong>reverse</strong> and <strong>transpose</strong> to produce the following arrays:</p>

<ol type="a">

<li><pre>1 1 1 1

0 1 1 1

0 0 1 1

0 0 0 1</pre></li>

<li><pre>0 0 0 1

0 0 1 1

0 1 1 1

1 1 1 1</pre></li>

<li><pre>1 1 1 1

1 1 1 0

1 1 0 0

1 0 0 0</pre></li>

</ol></li>

<li><p>Given the following variables:</p>

<pre> B← 'ABC' 'DEFG' 'IJKLM'

W← 3 4 ⍴'ABCDEFGHIJKL'</pre>

<p>Evaluate these expressions:</p>

<ol type="a">

<li><code>⌽W</code></li>

<li><code>⊖W</code></li>

<li><code>⌽⊖W</code></li>

<li><code>1⌽⊖W</code></li>

<li><code>1 2 3 0⊖W</code></li>

<li><code>⌽B</code></li>

<li><code>⌽¨B</code></li>

<li><code>1 2 ¯2⌽¨B</code></li>

</ol></li>

<li><p>Given the following array:</p>

<pre> A←3 4⍴⍳12</pre>

<p>Complete the following expressions to produce the stated results:</p>

<ol type="a" style="column-count: 2">

<li><pre> _________ A

4 3 2 1

8 7 6 5

12 11 10 9</pre></li>

<li><pre> _________ A

9 10 11 12

5 6 7 8

1 2 3 4</pre></li>

<li><pre> _________ A

12 11 10 9

8 7 6 5

4 3 2 1</pre></li>

<li><pre> _________ A

2 3 4 1

6 7 8 5

10 11 12 9</pre></li>

<li><pre> __________ A

3 4 1 2

7 8 5 6

11 12 9 10</pre></li>

<li><pre> _________ A

1 2 3 4

6 7 8 5

11 12 9 10</pre></li>

<li><pre> _________ A

2 3 4 1

5 6 7 8

12 9 10 11</pre></li>

<li><pre> _________ A

5 2 11 4

9 6 3 8

1 10 7 12</pre></li>

</ol>

</li>

<li><p>A <em>palindrome</em> is a string that reads the same both forward and backward.</p>

<ol type="a">

<li>Write an expression to determine if a vector <code>V</code> is a palindrome.</li>

<li>Given that <code>V</code> is a nested vector, write an expression that will determine which of the items of <code>V</code> are palindromes.</li>

</ol></li>

<li><p>Given a matrix <code>M</code>, write an expression to replace the main diagonal of <code>M</code> with</p>

<ol type="a">

<li>The number zero.</li>

<li>The character <code>'Z'</code>.</li>

<li>The character string <code>'DIAG'</code>.</li>

</ol></li>

<li><p>For the matrix <code>T</code>, write an expression to replace with zeros the items on the diagonal just to the right of the main diagonal.</p></li>

<li><p>Write an expression to test whether a given square matrix <code>S</code> is symmetric (that is, if <code>S[I;J]=S[J;I]</code> for all <code>I</code> and <code>J</code>.)</p></li>

<li><p>Write an expression that maps numeric vector <code>V</code> so the smallest number maps to <code>1</code>, the next smallest number maps to <code>2</code>, and so on until the largest number maps to <code>⍴V</code>. For example, the vector <code>53 47 95 6 77 78 83 13 2 69</code> should then map to the vector <code>5 4 10 2 7 8 9 3 1 6</code>.</p></li>

<li><p><code>M</code> and <code>N</code> are simple matrices having the same number of columns.</p>

<ol type="a">

<li>Write an expression to produce a Boolean vector which is 1 when the corresponding row of <code>M</code> is also a row of <code>N</code>.</li>

<li>Write an expression to determine which rows of <code>M</code> match rows in <code>N</code>. Return the row indices of <code>N</code> as the result.</li>

</ol></li>

<li><p>Suppose you have the following two character vectors:</p>

<pre> FROM ← 'ABCDEF'

TO ← 'abcdef'</pre>

<p>Write an expression using <code>FROM</code> and <code>TO</code> that converts the character string <code>'CAB'</code> to lower case.</p></li>

<li><p>Given simple scalar <code>S</code>, write an expression to find the first occurrence of <code>S</code> in each row of a matrix. If the scalar is not present, return a number one greater than the number of columns in the matrix.</p></li>

<li><p>State the shape, depth, and value of the following expressions:</p>

<ol type="a">

<li><code>'ABC' 'DEFG' ⍳ 'ABC'</code></li>

<li><code>'ABC' 'DEFG' ⍳ ⊂'ABC'</code></li>

<li><code>'ABC' 'DEFG' ⍳ ⊂'DEFG'</code></li>

<li><code>'ABC' 'DEFG' ⍳ 'XY'</code></li>

<li><code>'ABC' 'DEFG' ⍳ ⊂'XY'</code></li>

<li><code>'ABC' 'DEFG' ⍳ 'XY' 'ABC'</code></li>

<li><code>'ABC' 'DEFG' ⍳ ⊂'XY' 'ABC'</code></li>

<li><code>'ABC' 'DEFG' ⍳ (⊂'XY'),(⊂'ABC')</code></li>

<li><code>'ABC' 'DEFG' ⍳ (⊂'XY') (⊂'ABC')</code></li>

</ol></li>

<li><p>State the value of each of the following expressions, given:</p>

<pre> V← 20 23 17 30 12 9</pre>

<ol type="a">

<li><code>⍋V</code></li>

<li><code>⍒V</code></li>

<li><code>V[⍋V]</code></li>

<li><code>V[⍒V]</code></li>

<li><code>⍋⍋V</code></li>

</ol></li>

<li><p>State the value of each of the following expressions, given:</p>

<pre> AV←'ABCD ... Z'

NAMES←5 3⍴'TEETEAATEDADDAB'</pre>

<ol type="a">

<li><code>AV⍋NAMES</code></li>

<li><code>AV⍒NAMES</code></li>

<li><code>NAMES[AV⍋NAMES;]</code></li>

</ol></li>

<li><p>The find function (<code>⍷</code>) does not wrap around rows in searching an array. Write an expression to find a character string <code>V</code> in an array <code>A</code> even if the string wraps around in row-major order in the array. For example, searching for <code>XYZ</code> in this array:</p>

<pre> XYZX

YZXY

ZXYZ</pre>

<p>produces the following:</p>

<pre> 1 0 0 1

0 0 1 0

0 1 0 0</pre></li>

<li><p>Write a dyadic function <code>BLANKOUT</code> whose left argument is a set of characters which, if found in the right argument character string, are to be set to blanks. Here is an example:</p>

<pre> ‘,.’‘?!’ BLANKOUT ‘APL2 IS FUN!, ISN’‘T IT?’

APL2 IS FUN ISN T IT </pre></li>

</ol>

<h3 id="section-6.4-computation">Section 6.4 — Computation<a href="#section-6.4-computation" class="section-link">§</a></h3>

<p>You’ve already seen some of <span class="small-caps">APL2</span>’s computational functions such as <strong>addition</strong>, <strong>power</strong>, and <strong>magnitude</strong>. This section contains further discussion of <strong>power</strong> and introduces the rest of the <span class="small-caps">APL2</span> computational functions:</p>

<ul>

<li><strong>exponential</strong></li>

<li><strong>logarithm</strong></li>

<li><strong>decode</strong></li>

<li><strong>encode</strong></li>

<li><strong>factorial</strong></li>

<li><strong>binomial</strong></li>

<li><strong>trigonometric functions</strong></li>

<li><strong>matrix inverse</strong></li>

<li><strong>matrix divide</strong></li>

</ul>

<h4 id="power-and-exponential">Power and Exponential<a href="#power-and-exponential" class="section-link">§</a></h4>

<p><a href="chapter2.html">Chapter 2</a> introduced the <strong>power</strong> function. <strong>Power</strong> has some interesting properties that lead to a definition of the function on nonintegers.</p>

<p>Suppose you take the product of two powers of the same number:</p>

<pre> (2⋆2)×(2⋆3)

32</pre>

<p>This result is the same as <code>2⋆5</code>. Therefore, to compute the product of powers, add the exponents:</p>

<pre> (X⋆N) × (X⋆M) &lt;--&gt; X⋆(N+M)</pre>

<p>Several interesting cases can be derived from this. In each of the examples that follow, add the exponents to determine the results:</p>

<pre> (2⋆2)×(2⋆3)×(2⋆1)

64</pre>

<p>This example shows that <code>2⋆1</code> is the same as <code>2</code> because <code>(2⋆2)×(2⋆3)</code> is <code>(2⋆5)</code>, which is <code>32</code>. If multiplying also by <code>(2⋆1)</code> gives <code>64</code>, then <code>(2⋆1)</code> must be <code>2</code>.</p>

<pre> (2⋆2)×(2⋆3)×(2⋆0)

32</pre>

<p>This example shows that any number to the zero power is <code>1</code>. <code>(2⋆2)×(2⋆3)</code> is <code>(2⋆5)</code>, which is <code>32</code>. If multiplying by <code>(2⋆0)</code> also gives <code>32</code>, then <code>(2⋆0)</code> must be <code>1</code>.</p>

<p><strong>Power</strong> is not limited to nonnegative integer arguments. Here’s an expression with a negative exponent:</p>

<pre> (2⋆2)×(2⋆3)×(2⋆¯2)

8</pre>

<p><code>(2⋆2)×(2⋆3)</code> is the same as <code>(2⋆5)</code>, which is <code>32</code>. If multiplying by <code>(2⋆¯2)</code> gives <code>8</code>, then <code>(2⋆¯2)</code> must be the same as dividing by <code>(2⋆2)</code>, which is <code>4</code>. Thus, a negative exponent implies division by the same quantity with the exponent made positive.</p>

<p>Suppose that the exponents are not integers:</p>

<pre> (2⋆.1)×(2⋆.5)×(2⋆.4)

2</pre>

<p>The exponents add to <code>1</code> so the answer equals <code>2⋆1</code>. Use of fractional exponents gives rise to some common special cases of <strong>power</strong>. Consider this:</p>

<pre> (2⋆.5)×(2⋆.5)

2</pre>

<p>Again, the exponents sum to <code>1</code>. But what is <code>2⋆.5</code>? It is a number that when multiplied by itself gives <code>2</code>. In mathematics, such a number is a <strong><em>square root</em></strong>. <span class="small-caps">APL2</span> has no special square root function. It is just a special case of <strong>power</strong> with a right argument of one-half:</p>

<pre> 2⋆.5

1.414213562</pre>

<p>You may have heard that you cannot take the square root of a negative number. Try it on your system:</p>

<pre> ¯4⋆.5</pre>

<p>You might get one of two responses. This response means that your implementation supports only real numbers:</p>

<pre>DOMAIN ERROR

¯4⋆.5

^ ^</pre>

<p>This response means that your implementation supports complex numbers:</p>

<pre>0J2</pre>

<p>If you get this answer, enter the following:</p>

<pre> 0J2 × 0J2

¯4</pre>

<p>This result shows that <code>0J2</code> is the square root of <code>¯4</code>. The number <code>0J2</code> is called a complex number. In mathematics, a complex number is often written as an expression like 0<code>+</code>2i. Complex numbers are not discussed further in this book.</p>

<p>You indicate cube roots by using <strong>power</strong> with a right argument of one-third:</p>

<pre> 64⋆÷3

4</pre>

<p>In general, in <span class="small-caps">APL2</span>, enter <code>A⋆÷N</code> to take the <code>N</code>th root of a number <code>A</code>.</p>

<p>You saw, in the discussion of <strong>floor</strong> in <a href="chapter2.html">Chapter 2</a>, that you can compute a 5% interest one time as follows:</p>

<pre> AMOUNT←150.20 331.35 331.25

AMOUNT×1.05

157.71 347.9175 347.8125</pre>

<p>Suppose one year later you get 5% interest again on your amount. This is, again, 1.05 times the previous new amount:</p>

<pre> AMOUNT×1.05×1.05

165.5955 365.313375 365.203125</pre>

<p>Instead of using multiplication, you can compute the new amount using <strong>power</strong>:</p>

<pre> AMOUNT×1.05⋆2

165.5955 365.313375 365.203125</pre>

<p>Although there is not much difference between using a power of 2 and multiplication, the difference becomes significant if you require more repetitive multiplications. Suppose you get 5% every year for four years. Using <strong>power</strong>, you can compute the amount after four years with no more typing than computing the interest for two years:</p>

<pre> AMOUNT×1.05⋆4

182.5690388 402.7579959 402.6364453</pre>

<p>You may want to know your balance on each account at the end of each of the four years so you can see how your money grows. These are interest multiplication factors:</p>

<pre> (1.05)(1.05⋆2)(1.05⋆3)(1.05⋆4)

1.05 1.1025 1.157625 1.21550625</pre>

<p>These can be computed more compactly like this:</p>

<pre> 1.05⋆⍳4

1.05 1.1025 1.157625 1.21550625</pre>

<p>Now you want to multiply each amount by each factor. That is, you want all combinations of amounts with factors. You should remember from <a href="chapter5.html">Chapter 5</a> that <strong><em>all combinations</em></strong> means <strong>outer product</strong> in <span class="small-caps">APL2</span>. Thus, the desired computation is expressed as follows:</p>

<pre> AMOUNT ∘.× 1.05⋆⍳4

157.71 165.5955 173.875275 182.5690388

347.9175 365.313375 383.5790438 402.7579959

347.8125 365.203125 383.4632813 402.6364453</pre>

<p>Finally, you can round these amounts so they are easier to study:</p>

<pre> .01×⌊.5+100×AMOUNT ∘.× 1.05⋆⍳4

157.71 165.6 173.88 182.57

347.92 365.31 383.58 402.76

347.81 365.2 383.46 402.64</pre>

<p>When <strong>power</strong> is used without a left argument, it is <strong>exponential</strong>. <strong>Exponential</strong> is the same as power with a left argument of <code>2.718281828</code> (rounded to 10 places).</p>

<pre> ⋆2

7.389056099</pre>

<p>The constant 2.718281828 is often represented in mathematics by the letter e.</p>

<p>You can use <strong>power</strong> with an integer exponent and with a fractional exponent to express the famous Pythagorean Theorem: “In a right triangle, the length of the hypotenuse is the square root of the sum of the squares of the legs”:</p>

<center>

<img src="images/pythagoras.png">

</center>

<p>Suppose that the legs are of lengths <code>3</code> and <code>4</code>. The computation of the hypotenuse is follows:</p>

<pre> LEGS← 3 4

(+/LEGS⋆2)⋆.5

5</pre>

<h4 id="logarithm">Logarithm<a href="#logarithm" class="section-link">§</a></h4>

<p>You’ve just seen that, in a limited sense, <strong>power</strong> lets you compute products by doing addition (of the exponents). Addition is easy because even if you don’t know the algorithm for it, you can compute the sum of 2 and 3 with a ruler by measuring a string of length 2 laid next to a string of length 8. The famous mathematician Napier discovered a way to do the same thing for <strong>multiplication</strong> with a function called <strong>logarithm</strong>.</p>

<p>Napier marked off a ruler so the markings represented the exponents. Now adding lengths is like adding exponents and that is multiplication (as seen in the <strong>power</strong> section). Napier used ivory bars that became known as “Napier’s bones.” Robert Bissaker adapted the idea and built a ruler called a <em>slide rule</em> because it includes a sliding section to make addition of lengths easy. It was the mainstay of engineering calculations until the invention of the electronic calculator.</p>

<p><span class="small-caps">APL2</span> implements Napier’s function with the symbol <code>⍟</code> and calls it <strong>logarithm</strong>. <strong>Logarithm</strong> is certainly less familiar to most people than <strong>addition</strong> and <strong>subtraction</strong>. It is, however, just a function that, given one number, produces another number. All you need to know is what you can do with the function.</p>

<p>Here are some base-10 logarithms:</p>

<pre> 10⍟100

2

10⍟325

2.511883361

10⍟1000

3

10⍟10000

4</pre>

<p>Logarithms to the base 10 are sometimes called <em>common logarithms</em>. <strong>Logarithm</strong> is the inverse of the <strong>power</strong> function:</p>

<pre> N⍟(N⋆X) is X for N not zero

10⋆10⍟10000

10000</pre>

<p>In cases where the result is an integer, it is easy to see that <strong>logarithm</strong> is the inverse of <strong>power</strong> because, for example, 4 is the power of 10 that would give 10000.</p>

<p>Every number greater than or equal to 100 but less than 1000 has a logarithm with 2 as an integer part. Given this fact, <strong>logarithm</strong> can be used to compute the number of digits in any decimal number <code>N</code>. When you are programming a report, you can use the computation of the number of digits to determine how much space on a line some data will take. You can compute the number of integer digits by finding the integer part of <code>1+10⍟N</code>:</p>

<pre> 1+10⍟100

3

1+10⍟325

3.511883361</pre>

<p>Notice that leading zeros on a number have no effect:</p>

<pre> 1+10⍟00000325

3.511883361</pre>

<p>By convention, in a decimal number, leading zeros are not written unless there are no other digits.</p>

<p>You already know of a function that takes the integer part of a number—it’s <strong>floor</strong>. The following is a more complete expression for the number of digits in a number:</p>

<pre> N←345.76

10⍟N

2.53877475

⌊1+10⍟N

3</pre>

<p>To be completely general, this expression must be augmented in two ways. First, when counting digits in a number, the sign of the number is not relevant. You should apply the expression only to positive numbers. Here is the expression applied only to the <strong>magnitude</strong> of a number:</p>

<pre> ⌊1+10⍟∣N

3</pre>

<p>Second, zero is a special case. It is the only number that must be written with a leading zero. Otherwise, it would be written as an empty string of digits. An empty string would, in fact, be more correct, but it is difficult to distinguish it from no number at all. Therefore, we want to count one digit if the number is zero. Here, then, are two expressions for counting the number of integer digits:</p>

<pre> ⌊1+10⍟∣N+N=0

3

⌊1+10⍟1⌈∣N

3</pre>

<p>The monadic <strong>natural logarithm</strong> (<code>⍟</code>) function is the inverse of the monadic <strong>power</strong> functions:</p>

<pre> ⍟⋆X &lt;--&gt; X</pre>

<p>The following is an example:</p>

<pre> 2⋆6

64

2⍟2⋆6

6

⋆6

403.4287935

⍟⋆6

6</pre>

<h4 id="decode">Decode<a href="#decode" class="section-link">§</a></h4>

<p>In <a href="chapter5.html">Chapter 5</a>, you saw <strong>inner product</strong> used to convert hours, minutes, and seconds to seconds:</p>

<pre> 3600 60 1 +.× 2 15 30

8130</pre>

<p>The left argument had to be computed. <strong>Decode</strong> (<code>⊥</code>) is like <strong>inner product</strong>. (In fact, all the shape rules are identical.) The left argument of <strong>decode</strong> is, however, the units of measurement, not the conversion factors. Thus <strong>decode</strong> can achieve the same result as the above <strong>inner product</strong> as follows:</p>

<pre> 24 60 60⊥2 15 30

8130</pre>

<p>The left argument indicates 24 hours in a day, 60 minutes in an hour, and 60 seconds in a minute. Given a vector as an argument to <strong>decode</strong>, the corresponding argument to inner product is computed as follows:</p>

<pre> ⌽1,×\⌽1↓L</pre>

<p>Here is an example:</p>

<pre> ⌽1,×\⌽1↓24 60 60

3600 60 1</pre>

<p>From the formula, you can tell that the leftmost number in the left argument is not used and could be anything. The discussion of <strong>encode</strong> gives the reason for including the <code>24</code>.</p>

<p>In general, the following identity relates <strong>decode</strong> and <strong>inner product</strong>:</p>

<pre> L⊥R &lt;--&gt; (⌽1,×\⌽1↓L)+.×R</pre>

<p>You might think of time measurement as a counting system, or a <em>number system</em>. Seconds count from 0 to 59; then the minutes number increments, and the seconds go back to zero. When the minute count exceeds 59, hours increment. When hours exceed 23, days increment. (A common timekeeping system counts from 1 to 12 for hours, then increments a half-day counter, not from 0 to 1, but from <span class="small-caps">AM</span> to <span class="small-caps">PM</span>. This system takes a little more programming to support.)</p>

<p>A number system that uses a different value in each position is a <em>mixed radix</em>, or a <em>mixed base</em>, system. More uniform number systems have the same number of values in each position. By far the most common such number system is the Arabic, or decimal number, system based on 10 values in each position. Other common bases for number systems are 2, 8, and 16 (binary, octal, and hexadecimal). These are used mostly by computers. People use base 10 presumably because when the Arabs started using it, people had ten fingers. It’s too bad that they didn’t have twelve fingers because twelve has twice as many even divisors as ten (2, 3, 4, and 6 compared to 2 and 5). This would have reduced the number of fractions in everyday arithmetic.</p>

<p><span class="small-caps">APL2</span> numeric input and output is exclusively base 10.</p>

<p>If you have the digits of a decimal number, you can compute the scalar number they represent using <strong>decode</strong>:</p>

<pre> 10 10 10 10⊥1 9 8 8

1988</pre>

<p>If the number system is not mixed radix, you need not write a vector left argument:</p>

<pre> 10⊥ 1 9 8 8

1988</pre>

<p>This makes alternate number bases easy to convert to decimal. Here are conversions from bases 2 and 16:</p>

<pre> 2⊥0 1 0 1

5

16⊥ 0 1 9 15

415</pre>

<p>Any number on the left yields an answer:</p>

<pre> 137⊥1 2 5 7

2609583

1.1⊥1 2 5 7

16.251</pre>

<p>Base 137 is unreasonable and base 1.1 is strange. There is, however, another interpretation of decode. Consider the following polynomial:</p>

<center>

<math>

<mrow>

<msup>

<mi>X</mi>

<mn>3</mn>

</msup>

<mo>+</mo>

<mn>2</mn>

<mo>&InvisibleTimes;</mo>

<msup>

<mi>X</mi>

<mn>2</mn>

</msup>

<mo>+</mo>

<mn>5</mn>

<mo>&InvisibleTimes;</mo>

<mi>X</mi>

<mo>+</mo>

<mn>7</mn>

</mrow>

</math>

</center>

<p>The following expression evaluates the polynomial when <code>X</code> is 137:</p>

<pre> +/(137⋆3) (137⋆2) 137 1 × 1 2 5 7

2609583</pre>

<p>You can also write the evaluation of a polynomial as an <strong>inner product</strong> expression:</p>

<pre> (137⋆3) (137⋆2) 137 1 +.× 1 2 5 7

2609583</pre>

<p>Finally, you can write the evaluation of a polynomial as a <strong>decode</strong> expression:</p>

<pre> 137⊥1 2 5 7

2609583</pre>

<p>On higher-rank arrays, <strong>decode</strong> acts like <strong>inner product</strong> and applies the vector definition between rows from the left argument and columns from the right argument in all combinations:</p>

<pre> (2 3⍴24 60 60 10 10 10)⊥3 2⍴2 9 15 8 30 6

8130 32886

380 986</pre>

<h4 id="encode">Encode<a href="#encode" class="section-link">§</a></h4>

<p>You may think of <strong>encode</strong> (<code>⊤</code>) as doing the reverse operation of <strong>decode</strong>. (It’s not, correctly speaking, an inverse.) Given the total number of seconds, <strong>encode</strong> can compute the number of hours, minutes, and seconds:</p>

<pre> 24 60 60 ⊤8130

2 15 30</pre>

<p>Notice that this example uses the same left argument the first <strong>decode</strong> example used. Here, however, the 24 is necessary to limit the hours figure to the range 0 to 23. Here’s an example where the number of seconds is more than 24 hours:</p>

<pre> 24 60 60 ⊤813000

9 50 0</pre>

<p>Even though 813,000 seconds is more than 24 hours, the answer reflects time less than 24 hours. Two ways are available for you to capture the amount of time lost in this computation. First, you can add another item in the left argument to represent days of the week:</p>

<pre> 7 24 60 60 ⊤813000

2 9 50 0</pre>

<p>This method works only with a right argument that contains less than a week’s worth of seconds.</p>

<p>Second, <span class="small-caps">APL2</span> has a way to let one position in the result of an <strong>encode</strong> get arbitrarily large. A zero in the left argument means “accept any number in the corresponding position in the result”:</p>

<pre> 0 60 60 ⊤ 813000

225 50 0</pre>

<p>Numbers in the abstract can be arbitrarily large. An indefinite number of digits might be required to represent a number. When you encode numbers, you must know how many digits you want to represent. In a given problem, you usually know.</p>

<p>The following examples use <strong>encode</strong> to reverse the corresponding <strong>decode</strong> examples:</p>

<pre> 10 10 10 10⊤1988

1 9 8 8

2 2 2 2 27⊤5

0 0 1 0 1

(4⍴16)⊤415

0 1 9 15</pre>

<p>If you are working with polynomials, <strong>encode</strong> takes the value of a polynomial and the value of the variable and computes a set of coefficients:</p>

<pre> 137 137 137 137 ⊤26098583

1 2 5 7</pre>

<p>On higher-rank arrays, <strong>encode</strong> has the same shape rules as <strong>outer product</strong> and applies columns from the left argument against scalars from the right argument in all combinations:</p>

<pre> 4 2⍴ 10 16

10 16

10 16

10 16

10 16

(4 2⍴ 10 16)⊤137

0 0

1 0

3 8

7 9</pre>

<p>Notice that the encoding is along the leftmost axis of the result.</p>

<p>For more detailed information on <strong>encode</strong> with higher-rank arrays, see the documentation that comes with your system.</p>

<h4 id="factorial-and-binomial">Factorial and Binomial<a href="#factorial-and-binomial" class="section-link">§</a></h4>

<p>Monadic <strong>factorial</strong> and dyadic <strong>binomial</strong> are functions you can use to figure out combinatorial problems. These two functions are discussed in this section.</p>

<h5 id="factorial">Factorial<a href="#factorial" class="section-link">§</a></h5>

<p>Suppose you have a game consisting of five unique pieces labeled <code>A</code> through <code>E</code> which are arranged in a row. Here is one arrangement of the five pieces:</p>

<pre> DISPLAY 'ACBED'

.→----.

|ACBED|

'-----'</pre>

<p>How many different ways can you arrange these five pieces? For the leftmost position, you could choose any of the five pieces. For the second from the left position, you could choose any of the remaining four pieces. The third position could contain any of the remaining three pieces. The fourth position any of the remaining two pieces. And there is only one choice for the fifth position. The total number of possible arrangements is:</p>

<pre> 5×4×3×2×1

120

or

×/⍳5

120</pre>

<p>The monadic <strong>factorial</strong> function computes this result directly:</p>

<pre> !5

120</pre>

<p>The number of combinations possible when the pieces are not all distinct can also be computed easily. Suppose of the five pieces, three have the same label:</p>

<pre> DISPLAY 'ABAAC'

.→----.

|ABAAC|

'-----'</pre>

<p>There are still 120 arrangements but some look the same as others. For fixed <code>B</code> and <code>C</code>, you could choose any <code>A</code> for the first position, any of the remaining two for the third position, and have only one choice for the fourth position. Therefore, the number of ways to select the <code>A</code>’s is <code>3×2×1</code> which is <code>!3</code>. This is true for every choice of position for <code>B</code> and <code>C</code>, so the number of distinct arrangements is the total number of arrangements divided by the number of arrangements not distinguishable:</p>

<pre> (!5)÷!3

20</pre>

<p>If you have six white marbles and four black ones, you compute the number of distinct linear arrangements:</p>

<pre> (!10)÷(!6)×(!4)

210

or

(!10)÷×/!6 4

210</pre>

<p>Note: <strong>factorial</strong> is related to the <strong><em>gamma</em></strong> function of higher mathematics as follows:</p>

<pre> !A &lt;--&gt; gamma A+1</pre>

<p>This relationship is used to define <strong>factorial</strong> on noninteger and non-positive numbers. The <strong><em>gamma</em></strong> function is not discussed further in this book.</p>

<h5 id="binomial">Binomial<a href="#binomial" class="section-link">§</a></h5>

<p>Suppose you have seven distinct pieces and you select three of them. How many ways can you select three things from a collection of seven? You can choose any of the seven for the first selection, any of the remaining six for the second selection, and any of the remaining five for the third selection. Thus, the number of selections is:</p>

<pre> 7×6×5

210</pre>

<p><strong>Factorial</strong> 7 is <code>7×6×5×4×3×2×1</code>. Clearly, if you divide by <code>4×3×2×1</code> (which is <code>!7−3</code>), you get the desired result:</p>

<pre> (!7)÷!7−3

210</pre>

<p>In general, to select <code>R</code> things in order from a set of <code>L</code> things, you evaluate the following expression:</p>

<pre> (!L)÷!L−R</pre>

<p>If the order of the selected items doesn’t matter when selecting three items from a set of seven items, there are <code>!3</code> different arrangements which contain the same three pieces. Dividing by the number of arrangements giving the same pieces gives the count of the number of different selections ignoring order:</p>

<pre> (!7)÷(!7−3)×!3

35</pre>

<p>Selecting items from a collection without regard to order is a common operation. The dyadic <strong>binomial</strong> function computes this more compactly:</p>

<pre> 3!7

35</pre>

<p>Formally, <strong>binomial</strong> is defined for all numbers by the following equation:</p>

<pre> L!R &lt;--&gt; (!R)÷(!R−L)×!L</pre>

<p>Note: <strong>Binomial</strong> is related to the mathematical <strong><em>beta</em></strong> function.</p>

<h4 id="trigonometric-functions">Trigonometric Functions<a href="#trigonometric-functions" class="section-link">§</a></h4>

<p><span class="small-caps">APL2</span> has a full set of trigonometric, hyperbolic, and pythagorian functions whose derivations are based on the analysis of circles. If you have no current use for these functions, you can skip this section.</p>

<h5 id="pi-times">Pi-times<a href="#pi-times" class="section-link">§</a></h5>

<p>A fundamental constant related to circles is <strong><em>pi</em></strong> (π), which is the number of circle diameters equal to the circumference of a circle. <span class="small-caps">APL2</span>’s monadic primitive <strong>pi-times</strong> (<code>○</code>) computes products of <strong><em>pi</em></strong>:</p>

<pre> ○1

3.141592654

○3

9.424777961</pre>

<p>The circumference of a circle with radius <code>R</code> is computed with <strong>pi-times</strong> as follows:</p>

<pre> ○2×R</pre>

<p>In science and mathematics, angles are often analyzed by looking at them in a right triangle imbedded in a unit circle with the vertex of the angle in question at the center of the circle:</p>

<center>

<img src="images/unit_circle.png">

</center>

<p>The angle θ is normally measured by measuring the length of the segment of the circumference it intersects. If it intersects a length equal to the radius of the circle, the angle has a measure of one radian. A full circle, therefore, contains 2<code>×</code><strong><em>pi</em></strong> radians. People often measure angles in degrees, and a circle has 360 degrees. The conversion of degrees to radians derives from the fact that 360 degrees is 2<code>×</code><strong><em>pi</em></strong> radians. Thus, one degree is (<strong><em>pi</em></strong> radians)<code>÷</code>180.</p>

<p>Using <strong>pi-times</strong>, the following expressions convert 45 degrees to radians:</p>

<pre> 45×○÷180

0.7853981634

or

○45÷180

0.7853981634</pre>

<h5 id="circular-functions">Circular Functions<a href="#circular-functions" class="section-link">§</a></h5>

<p><span class="small-caps">APL2</span> includes 25 functions related to circles. Rather than assign each of them a unique symbol, <span class="small-caps">APL2</span> packages the entire set in the dyadic; circular function (<code>○</code>), where the left argument integer specifies which monadic function is desired. The following table summarizes the circular functions available in <span class="small-caps">APL2</span> Table entries 8-12 apply to complex numbers.</p>

<center>

<table>

<caption>Table 6.4 Circular Functions</caption>

<thead>

<tr class="header">

<th style="text-align: left;">Negative <code>L</code></th>

<th style="text-align: left;"><code>L</code></th>

<th style="text-align: left;">Positive <code>L</code></th>

</tr>

</thead>

<tbody>

<tr>

<td class="l t r" style="text-align: left;"><code>(1−R*2)*.5</code></td>

<td class="l t r" style="text-align: left;"><code>&nbsp;0</code></td>

<td class="l t r" style="text-align: left;"><code>(1−R⋆2)*.5</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;">Arc sine <code>R</code></td>

<td class="l r" style="text-align: left;"><code>&nbsp;1</code></td>

<td class="l r" style="text-align: left;">Sine <code>R</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;">Arc cosine <code>R</code></td>

<td class="l r" style="text-align: left;"><code>&nbsp;2</code></td>

<td class="l r" style="text-align: left;">Cosine <code>R</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;">Arc tangent <code>R</code></td>

<td class="l r" style="text-align: left;"><code>&nbsp;3</code></td>

<td class="l r" style="text-align: left;">Tangent <code>R</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;"><code>(¯1−R*2)*.5</code></td>

<td class="l r" style="text-align: left;"><code>&nbsp;4</code></td>

<td class="l r" style="text-align: left;"><code>(1+R⋆2)*.5</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;">Inverse hyperbolic sine <code>R</code></td>

<td class="l r" style="text-align: left;"><code>&nbsp;5</code></td>

<td class="l r" style="text-align: left;">Hyperbolic sine <code>R</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;">Inverse hyperbolic cosine <code>R</code></td>

<td class="l r" style="text-align: left;"><code>&nbsp;6</code></td>

<td class="l r" style="text-align: left;">Hyperbolic cosine <code>R</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;">Inverse hyperbolic tangent <code>R</code></td>

<td class="l r" style="text-align: left;"><code>&nbsp;7</code></td>

<td class="l r" style="text-align: left;">Hyperbolic tangent <code>R</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;"><code>−(¯1−R*2)*.5</code></td>

<td class="l r" style="text-align: left;"><code>&nbsp;8</code></td>

<td class="l r" style="text-align: left;"><code>(¯1−R⋆2)*.5</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;"><code>R</code></td>

<td class="l r" style="text-align: left;"><code>&nbsp;9</code></td>

<td class="l r" style="text-align: left;">Real <code>R</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;"><code>+R</code> (conjugate)</td>

<td class="l r" style="text-align: left;"><code>10</code></td>

<td class="l r" style="text-align: left;"><code>∣R</code></td>

</tr>

<tr>

<td class="l r" style="text-align: left;"><code>0J×R</code></td>

<td class="l r" style="text-align: left;"><code>11</code></td>

<td class="l r" style="text-align: left;">Imaginary <code>R</code></td>

</tr>

<tr>

<td class="l r b" style="text-align: left;"><code>*0J1×R</code></td>

<td class="l r b" style="text-align: left;"><code>12</code></td>

<td class="l r b" style="text-align: left;">Phase <code>R</code></td>

</tr>

</tbody>

</table>

</center>

<p>Note: If complex numbers are not implemented on your system, the positive numbers above <code>7</code> and the negative numbers below <code>¯7</code> will not be available.</p>

<p>Many of the relationships between these functions can be seen by looking at a triangle in a unit circle:</p>

<center>

<img src="images/circle_functions.png">

</center>

<p>For example, you may have seen this trigonometric equation:</p>

<center>

<math>

<mrow>

<mn>1</mn>

<mo>↔</mo>

<msup>

<mo>COS</mo>

<mn>2</mn>

</msup>

<mi>θ</mi>

<mo>+</mo>

<msup>

<mo>SIN</mo>

<mn>2</mn>

</msup>

<mi>θ</mi>

</mrow>

</math>

</center>

<p>This equation is tested in <span class="small-caps">APL2</span> at 30 degrees by the following expression:</p>

<pre> +/(1 2○○30÷180)⋆2

1</pre>

<p>If you solve for <strong><em>sine</em></strong> in the equation, you get the following:</p>

<center>

<math>

<mrow>

<mo>SIN</mo>

<mi>θ</mi>

<mo>↔</mo>

<msqrt>

<mrow>

<mn>1</mn>

<mo>-</mo>

<msup>

<mo>COS</mo>

<mn>2</mn>

</msup>

<mi>θ</mi>

</mrow>

</msqrt>

</mrow>

</math>

</center>

<p>This is the value computed by <code>0○</code>. Thus, given a value of <strong><em>sine</em></strong>, you can use <code>0○</code> to solve for the value of <strong><em>cosine</em></strong> for the same angle.</p>

<h4 id="matrix-inverse">Matrix Inverse<a href="#matrix-inverse" class="section-link">§</a></h4>

<p>A function <strong><em>f</em></strong> is an inverse of function <strong><em>g</em></strong> if applying <strong><em>f</em></strong> to the result of <strong><em>g</em></strong> gives an identity of some kind. For example, in ordinary arithmetic, <strong>multiplication</strong> and <strong>division</strong> are inverses because a number times its reciprocal is 1 which is the identity of multiplication:</p>

<pre> N←÷20

N

0.05

N×20

1</pre>

<p><strong>Multiplication</strong> and <strong>division</strong> are scalar functions and extend to arrays like all scalar functions.</p>

<pre> N←÷20 10 5

N

0.05 0.1 0.2

N×20 10 5

1 1 1</pre>

<p>You’ve seen <strong>inner product</strong> with operands <code>+</code> and <code>×</code> in <a href="chapter5.html">Chapter 5</a>. When applied to simple scalars, <strong>inner product</strong> with these operands is like multiplication:</p>

<pre> N+.×20

1</pre>

<p><span class="small-caps">APL2</span> has a <code>⌹</code> function which is like <strong>reciprocal</strong> on simple scalars and is the inverse of <code>+.×</code>:</p>

<pre> N←⌹20

N

0.05

N+.×20

1</pre>

<p>When applied to non-scalars, <code>+.×</code> and <code>⌹</code> are not scalar functions:</p>

<pre> I←3 3⍴14 ¯140 168 ¯40 640 ¯840 27 ¯540 756

I

14 ¯140 168

¯40 640 ¯840

27 ¯540 756

⌹I

0.3333333333 0.1666666667 0.1111111111

0.08333333333 0.06666666667 0.05555555556

0.04761904762 0.04166666667 0.03703703704</pre>

<p><strong>Inner product</strong> with <code>+</code> and <code>×</code> is the algebraic <strong><em>matrix product</em></strong>, and <code>⌹</code> is the algebraic <strong><em>matrix inverse</em></strong> which is <span class="small-caps">APL2</span>’s <strong>matrix inverse</strong> function. The <code>+.×</code> <strong>inner product</strong> of any array with its matrix inverse is the <em>identity matrix</em> with <code>1</code>’s along the main diagonal and <code>0</code>’s everywhere else:</p>

<pre> (⌹I)+.× I

1 0 0

0 1 0

0 0 1</pre>

<p>Computation of a matrix inverse is a complicated procedure that is subject to numerical errors. The answer given by your <span class="small-caps">APL2</span> implementation may not lead to a perfect identity matrix for the preceding example. For example, if your computer can store 16 digits, <code>1E¯16</code> or <code>1E¯15</code> for off-diagonal items are close to zero when compared to the <code>1</code>’s on the diagonal.</p>

<p><strong>Matrix inverse</strong> must be applied to a matrix whose rows are linearly independent (that is, you can’t combine some rows by addition, subtraction, and multiplication by a scalar and produce one of: the other rows). If the rows are not linearly independent, the matrix is called singular and <code>⌹</code> produces a <code>DOMAIN ERROR</code>.</p>

<p>You may apply <strong>matrix inverse</strong> to a non-square matrix that has more rows than columns as long as there are as many independent rows as there are columns. In this case, a left inverse is produced:</p>

<pre> II← 5 2⍴1 1 1 2 1 3 1 4 1 5

⌹II

0.8 0.5 2.000000000E¯1 ¯0.1 ¯0.4

¯0.2 ¯0.1 ¯4.678201316E¯17 0.1 0.2

(⌹II)+.×II

1 0

0 1</pre>

<p>More than one answer which would be a left identity and produce an identity matrix is possible for the result of <code>⌹</code> in the above example. <span class="small-caps">APL2</span> produces the result that, for <code>M←⌹A</code> and <code>ID←M+.×A</code>, gives the smallest number in this equation:</p>

<pre> +/,(ID−A+.×M)⋆2</pre>

<p>Producing the result in this way is called a <em>least squares fit</em>.</p>

<h4 id="matrix-divide">Matrix Divide<a href="#matrix-divide" class="section-link">§</a></h4>

<p><strong>Matrix inverse</strong> can be used to solve systems of linear equations. Here is an example:</p>

<center>

<math>

<mrow>

<mtable columnalign="right center right center left center left" columnspacing=20%>

<mtr>

<mtd>

<mi>X</mi>

</mtd>

<mtd>

<mo>+</mo>

</mtd>

<mtd>

<mi>Y</mi>

</mtd>

<mtd>

<mo>+</mo>

</mtd>

<mtd>

<mi>Z</mi>

</mtd>

<mtd>

<mo>=</mo>

</mtd>

<mtd>

<mn>3</mn>

</mtd>

</mtr>

<mtr>

<mtd>

<mn>4</mn>

<mo>&InvisibleTimes;</mo>

<mi>X</mi>

</mtd>

<mtd>

<mo>+</mo>

</mtd>

<mtd>

<mn>2</mn>

<mo>&InvisibleTimes;</mo>

<mi>Y</mi>

</mtd>

<mtd>

<mo>+</mo>

</mtd>

<mtd>

<mi>Z</mi>

</mtd>

<mtd>

<mo>=</mo>

</mtd>

<mtd>

<mn>8</mn>

</mtd>

</mtr>

<mtr>

<mtd>

<mn>9</mn>

<mo>&InvisibleTimes;</mo>

<mi>X</mi>

</mtd>

<mtd>

<mo>+</mo>

</mtd>

<mtd>

<mn>3</mn>

<mo>&InvisibleTimes;</mo>

<mi>Y</mi>

</mtd>

<mtd>

<mo>+</mo>

</mtd>

<mtd>

<mi>Z</mi>

</mtd>

<mtd>

<mo>=</mo>

</mtd>

<mtd>

<mn>15</mn>

</mtd>

</mtr>

</mtable>

</mrow>

</math>

</center>

<p>These equations are satisfied when <code>X</code> is 1, <code>Y</code> is 2, and <code>Z</code> is 0. Here is the solution using <strong>matrix inverse</strong>:</p>

<pre> SE←3 3⍴ 1 1 1 4 2 1 9 3 1

SE

1 1 1

4 2 1

9 3 1

(⌹SE)+.×3 8 15

1 2 0</pre>

<p><strong>Matrix divide</strong> (<code>⌹</code>) does this computation in a single operation, where the right argument is a matrix of coefficients and the left argument is a vector of results for the equations:</p>

<pre> 3 8 15⌹SE

1 2 ¯2.664535259E¯15</pre>

<p>If the right argument has more rows than columns, the solution <span class="small-caps">APL2</span> chooses is one that, for <code>S←B⌹A</code>, minimizes this equation:</p>

<pre> +/,(B−A+.×S)⋆2</pre>

<p>Producing the result in this way is also called a <em>least squares fit</em>.</p>

<h4 id="exercises-for-section-6.4">Exercises for Section 6.4<sup class="answers-note">[<a href="answers.html#section-6.4-computation">Answers</a>]</sup><a href="#exercises-for-section-6.4" class="section-link">§</a></h4>

<ol>

<li><p>Suppose you invested one penny in the year 1776 and received 5% interest each year (no rounding). How much money would you have in 1987, 211 years later? Suppose you invested 50 pennies at the same rate. How much money would you have in 1987?</p></li>

<li><p>You decide to make a trip around the world by balloon and you take with you $100 (USD). You never spend any money, but every time you cross a national boundary, you convert your money into the local currency. You are charged a 5% fee each time you convert money.</p>

<ol type="a">

<li>Write an expression that computes the amount of money you have after entering the sixth country. Hint: Treat the service charge as negative interest.</li>

<li>It costs one dollar to send a telegram back home. What is the largest number of countries you can visit before sending home for more money? Hint: Use <strong>interval</strong> (<code>⍳</code>) for experimentally locating the time when your money would drop below one dollar.</li>

</ol></li>

<li><p>Notebooks come in ring sizes that increment by .5 inches. Every .5 inch can accommodate 100 sheets of paper. Define a function called <code>SIZE</code> that, given a vector of the number of sheets <code>S</code> in a set of manuals, returns the size binder to purchase for each manual.</p>

<p>Here is a sample execution:</p>

<pre> SIZE 200 250 263 310

2 2.5 3 3.5</pre></li>

<li><p>Write an expression to express an arbitrary integer in base 2. For example, applied to the number 17, you should get <code>1 0 0 0 1</code> Hint: Use a base-2 logarithm to compute the number of digits.</p></li>

<li><p>You saw <strong>indexing</strong> used to produce a histogram. Here is the sales data for a for each month of the year 1987:</p>

<pre> AMPL← 1005 1011 1017 1009 1023 1024 1021

AMPL←AMPL,1029 1031 1029 1035 1037</pre>

<ol type="a">

<li><p>What is the total number of sales in 1987?</p></li>

<li><p>What was the largest number sold in a month?</p></li>

<li><p>If one sale represents $137 in profit, what is the total profit for the year?</p></li>

<li><p>If each sale is really a lease with a monthly rental, then a sale in January is worth more than a sale in December. What is the total profit for the year, if each sale generates $13 per month starting in the month it is sold?</p></li>

<li><p>The sales manager wants to see a histogram of this data. You could easily use <strong>outer product</strong> and <strong>indexing</strong> to plot the graph:</p>

<pre> ' ⎕'[1+(1040−⍳1039)∘.≤AMPL]</pre>

<p>But a plot over a thousand lines long is not desirable. Scale the data so all of it falls in the range 0 to 20. Using <strong>indexing</strong>, plot a histogram of the resulting data.</p></li>

<li><p>The marketing manager wants to show more dramatic growth with the data from part e. Plot just the top of the histogram by subtracting 1000 from the data and then scaling to the range 0 to 20.</p></li>

</ol></li>

<li><p>Write an expression to convert an integer to a character string that represents an eight-digit signed hexadecimal (base 16) number. Here is an example:</p>

<pre> 12 converts to 0000000C

¯1 converts to FFFFFFFF</pre></li>

<li><p>Write an expression to convert a character string that represents a hexadecimal number to a signed integer.</p></li>

<li><p>Suppose you have a perfectly spherical globe. This globe has a radius of 45 prats (a unit of measure used nowhere in the civilized world).</p>

<ol type="a">

<li>If you tie a string around the equator on the globe, write an expression to determine the length of the string (ignoring the extra string it takes to tie the knot).</li>

<li>If you want the string to be off the surface of the globe 10 prats over the equator (assuming you have some way of suspending it there), how much string would you have to add?</li>

<li>Suppose the planet Xtric is a perfect sphere with a string wrapped tightly around its equator. If you want the string to be 10 prats off the surface over the equator, how much string would you have to add, assuming that the radius of Xtric is 45,000,000 prats?</li>

</ol></li>

<li><p>Assume the earth revolves about the sun in a circular orbit. If the distance from the earth to the sun is <code>DIST</code> miles, and the earth takes 364.25 days to complete one revolution, at what rate in miles per second is the earth traveling about the sun?</p></li>

<li><p>The article <em>“Engineering Voyager 2’s Encounter with Uranus”</em> in the November 1986 issue of <strong><em>Scientific American</em></strong> described the remarkable engineering feat of sending a satellite through the solar system past Uranus. As it passed the planet, the satellite transmitted 6000 images of Uranus back to earth. Each of these images consisted of 800 rows of 800 pixels. Because each pixel could represent one of 256 brightness levels, there were 8‘b1ts per pixel, or 5,120,000 bits per image. The data transmission rate was 21.6 kilobits per second. Determine the amount of time that was required to transmit all the images back to the earth. Give this time in terms of weeks, days, minutes, and seconds.</p></li>

<li><p>In hilly areas, road signs indicate the grade of the road with a pair of numbers such as 1:7. In this pair <em>a:b</em>, the first number <em>a</em> defines the amount of drop (or climb) vertically that occurs while moving horizontally <em>b</em> units. Write a function to accept a pair of grade numbers and determine the angle in degrees from the horizontal of the grade.</p></li>

<li><p>Evaluate the following expressions:</p>

<ol type="a">

<li><code>⌊⌹(⍳4)∘.≥⍳4</code></li>

<li><code>⌊⌹(⍳4)∘.≤⍳4</code></li>

</ol></li>

<li><p>Suppose one object is traveling at velocity <code>X</code> and another is traveling at velocity <code>Y</code> in the opposite direction. If the objects are moving slow enough, you can just add velocities. If they are on the earth, however, they begin to travel around the curvature of the earth and their relative velocity is less than the sum of their velocities. In space, the relative velocity of two objects traveling in opposite directions is controlled by Lorentz’s equation:</p>

<center>

<math>

<mrow>

<mfrac>

<mrow>

<mi>X</mi>

<mo>+</mo>

<mi>Y</mi>

</mrow>

<mrow>

<mn>1</mn>

<mo>+</mo>

<msqrt>

<mrow>

<mfrac>

<mrow>

<mi>X</mi>

<mo>+</mo>

<mi>Y</mi>

</mrow>

<mrow>

<msup>

<mi>C</mi>

<mn>2</mn>

</msup>

</mrow>

</mfrac>

</mrow>

</msqrt>

</mrow>

</mfrac>

</mrow>

</math>

</center>

<p>where <code>C</code> is the speed of light (300,000 meters per second).</p>

<p>Suppose the two velocities are represented in the vector <code>V</code>:</p>

<ol type="a">

<li><p>Write an expression to compute the relative velocity.</p></li>

<li><p>Suppose that each object is traveling at half the speed of light. What is their relative velocity?</p>

<p>By analogy with objects traveling on the earth, Einstein reasoned that, since the relative velocity was less than the sum, space was curved.</p></li>

</ol></li>

<li><p>State the value of each of the following expressions:</p>

<ol type="a">

<li><code>10⊥ 2 7 0 5</code></li>

<li><code>6⊥ 2 3 4</code></li>

<li><code>2 4 6 ⊥2 3 4</code></li>

<li><code>10 10 ⊥ 8</code></li>

<li><code>10 10 10 ⊥8</code></li>

<li><code>2 3 4⊥8</code></li>

<li><code>12⊥5 11</code></li>

<li><code>2 12⊥5 11</code></li>

<li><code>0 12⊥5 11</code></li>

<li><code>2 ⊥ 1 1 0 1 1</code></li>

<li><code>5 8 10 ⊥ 2 3 4</code></li>

<li><code>(,['']5 8 10) ⊥2 3 4</code></li>

<li><code>2 ⊥¨ (1 1 0 1 1)(1 1 0 1)</code></li>

<li><code>24 60 60 ⊥ 1 30 45</code></li>

</ol></li>

<li><p>State the value of each of the following expressions:</p>

<ol type="a">

<li><code>8 ⊤ 123</code></li>

<li><code>8 8 ⊤ 123</code></li>

<li><code>8 8 8 ⊤ 123</code></li>

<li><code>0 8 ⊤ 123</code></li>

<li><code>0 8 8 ⊤ 123</code></li>

<li><code>24 60 60 ⊤ 1 45 37</code></li>

<li><code>0 60 ⊤ 1 45 37</code></li>

<li><code>(4 3⍴2 8 10) ⊤ 13</code></li>

<li><code>(4 3⍴2 8 10) ⊤ 13 21</code></li>

<li><code>(⊂4 3⍴2 8 10) ⊤¨ 12 21</code></li>

</ol></li>

</ol>

<h3 id="section-6.5-generating-random-numbers">Section 6.5 — Generating Random Numbers<a href="#section-6.5-generating-random-numbers" class="section-link">§</a></h3>

<p>You saw an encoding of a message that replaced each letter by its position in the roman alphabet. Anyone might guess your method if you encode a message this way. A better way to encode a message would be to use a random arrangement of the alphabet. This section introduces some functions that can be used in this solution.</p>

<h4 id="deal">Deal<a href="#deal" class="section-link">§</a></h4>

<p><strong>Deal</strong> (<code>?</code>) generates random numbers. The expression <code>A?B</code> generates <code>A</code> random selections from the set of integers <code>⍳B</code> without replacement (that is, no number occurs twice):</p>

<pre> 5?10

1 3 6 2 4

5?10

3 1 9 5 2</pre>

<h4 id="roll">Roll<a href="#roll" class="section-link">§</a></h4>

<p>The function <strong>roll</strong> (<code>?</code>) generates one random integer for each integer in the argument. Here is an example:</p>

<pre> ? 10 10 10 10 10

1 5 1 2 4</pre>

<p>Each selection is independent, so duplicate integers can occur.</p>

<p>You can generate a random roll of a pair of dice as follows:</p>

<pre> ?6 6

3 5</pre>

<p>Here’s a way to encode a message using a random permutation of the alphabet A through Z plus blank:</p>

<pre> ALPH1←ALPH[27?27]

ALPH1

XGNLRUZVB ICOYTDKMQEPJAHSFW</pre>

<p>The dyadic function <strong>deal</strong> (<code>?</code>) computes 27 (left argument) different random integers from 1 to 27 (right argument). If you try this at your computer, you will probably get different numbers because <strong>deal</strong> does not necessarily produce the same random selection in two consecutive executions.</p>

<p>Using this permuted alphabet, you can get integers that are not related to the position of letters in the roman alphabet:</p>

<pre> NUM1←ALPH1⍳'SECRET MESSAGE'

NUM1

25 20 12 5 20 15 10 18 20 25 25 23 2 20</pre>

<p>If you would prefer to see some nonsense letters instead of numbers you can turn the integers into characters:</p>

<pre> MESS1←ALPH[ALPH1⍳'SECRET MESSAGE']

MESS1

YTLETOJRTYYWBT</pre>

<p>If you know the encoding alphabet <code>ALPH1</code>, the code is easy to break by using indexing:</p>

<pre> ALPH1[NUM1]

SECRET MESSAGE

ALPH1[ALPH⍳MESS1]

SECRET MESSAGE</pre>

<p>Now you have an encoding that is not so easy to guess. There are <code>!27</code> different possible alphabets that could arise from the random selection of 27 items:</p>

<pre> !27

1.088886945E28</pre>

<p><strong>Factorial</strong> determines the different possible alphabets because there are 27 choices for the substitution for <code>'A'</code>, then 26 choices for the substitution for <code>'B'</code>, and so forth.</p>

<h4 id="exercises-for-section-6.5">Exercises for Section 6.5<sup class="answers-note">[<a href="answers.html#section-6.5-generating-random-numbers">Answers</a>]</sup><a href="#exercises-for-section-6.5" class="section-link">§</a></h4>

<ol>

<li>In each of the following sets of expressions, one expression will satisfy the given statement. Determine which one it is.

<ol type="a">

<li>Select with replacement two random integers chosen from the set of integers <code>⍳10</code>.

<ol>

<li><code>?11 11</code></li>

<li><code>?11 10</code></li>

<li><code>?10 10</code></li>

<li><code>2?10</code></li>

<li><code>2?11</code></li>

</ol></li>

<li>Select without replacement two integers chosen from the set of integers <code>⍳10</code>.

<ol>

<li><code>?11 11</code></li>

<li><code>?11 10</code></li>

<li><code>?10 10</code></li>

<li><code>2?10</code></li>

<li><code>2?11</code></li>

</ol></li>

<li>Select with replacement two random integers chosen from the set of integers between <code>¯5</code> and <code>5</code>, excluding both <code>¯5</code> and <code>5</code>.

<ol>

<li><code>¯6+2?10</code></li>

<li><code>¯6+?10 10</code></li>

<li><code>¯5+?10 10</code></li>

<li><code>-5+?9 9</code></li>

<li><code>¯5+?9 9</code></li>

<li><code>¯5+2?9</code></li>

<li><code>¯6+2?10</code></li>

</ol></li>

<li>Select without replacement three random integers chosen from the set of integers between <code>¯5</code> and <code>5</code>, inclusive.

<ol>

<li><code>¯6+3?10</code></li>

<li><code>¯6+?10 10 10</code></li>

<li><code>¯5+3?10</code></li>

<li><code>¯5+?10 10 10</code></li>

<li><code>¯5+3?11</code></li>

<li><code>¯5+?11 11 11</code></li>

<li><code>¯6+3?11</code></li>

<li><code>¯6+?11 11 11</code></li>

</ol></li>

</ol></li>

<li>Write an expression to represent each of the following statements:

<ol type="a">

<li>The roll of four dice.</li>

<li>The deal of five cards from a standard deck of cards.</li>

<li>A prime number selected at random from the first six prime numbers.</li>

<li>A vector such that its dimension is no greater than 10, and each item is a random integer less than or equal to 25.</li>

<li>A matrix of three rows and four columns containing positive random integers all less than 100.</li>

<li>A two-decimal place random number between 0 and 1. Both 0 and 1 are to be excluded.</li>

</ol></li>

<li>Given a vector of names <code>NAMES</code>, write an expression for each of the following:

<ol type="a">

<li><p>Select a name at random to assign to do dishes.</p></li>

<li><p>Rearrange the names arbitrarily for a chore list. Test your expressions on the following vector:</p>

<pre> NAMES← 'ANNE' 'STACY' 'SCOTT' 'DAVID'</pre></li>

</ol></li>

</ol>

<footer>

<table width=100%>

<tr>

<td style="text-align: left">

[<a href="chapter5.html"><code>←</code></a>]

</td>

<td style="text-align: center">

[<a href="contents.html"><code>↑</code></a>]

</td>

<td style="text-align: right">

[<a href="chapter7.html"><code>→</code></a>]

</td>

</tr>

</table>

</footer>

View this page on the web

View page source