NYCJUG/2019-03-12

From J Wiki
Jump to navigation Jump to search

Beginner's regatta

We look at how to implement two types of fold from Haskell in J and we compare the areas of different standard camera sensors.

Haskell's "Foldl" and "Foldr" in J

The functional language Haskell has two flavors of what we would call "reduction": Foldl and Foldr. Here is what they do, first as shown in R:

a = [8,3,4]

## Foldl
reduce(lambda x,y: x**y, a)
#68719476736

## Foldr
reduce(lambda x,y: y**x, a[::-1])
#14134776518227074636666380005943348126619871175004951664972849610340958208L

It was the consensus in the meeting that Foldl was the more commonly used in practice.

Now in J:

   ^~/|.8 3 4x    NB. Foldl
68719476736
   ^/8 3 4x       NB. Foldr
14134776518227074636666380005943348126619871175004951664972849610340958208

So, "Foldr" corresponds to normal reduction and "Foldl" corresponds to reflexive application on a reversed vector.

Comparing Camera Sensor Sizes

We look at the length and width of various types of camera sensor to compare their areas.

[From https://en.wikipedia.org/wiki/Image_sensor_format]

In digital photography, the image sensor format is the shape and size of the image sensor.

The image sensor format of a digital camera determines the angle of view of a particular lens when used with a particular sensor. Because the image sensors in many digital cameras are smaller than the 24 mm × 36 mm image area of full-frame 35 mm cameras, a lens of a given focal length gives a narrower field of view in such cameras.

CamerasComparison-sensor size.jpg Sensor sizes overlaid inside.svg.png

Above we see an example of the specifications of different cameras; we are concerned with the sensor size.

Name Dimensions (mm)
Full frame 35.8 x 23.9
APS-C 23.7 x 15.7
1″ 13.2 x 8.8
Four Thirds 17.3 x 13.0
1/2.33″ 6.08 x 4.56

Putting the dimensions only into a numeric table allows us to multiply them to get the different areas.

   $dims=. 35.8 23.9,23.7 15.7,13.2 8.8,17.3 13,:6.08 4.56
5 2
   dims
35.8 23.9
23.7 15.7
13.2  8.8
17.3   13
6.08 4.56
   */"1 dims
855.62 372.09 116.16 224.9 27.7248

   *:25.4      NB. FYI: 1 in^2 = 645 mm^2
645.16

We can then order the areas from largest to smallest and divide them by the smallest to get the relative areas.

   (]%<./)\:~*/"1 dims
30.8612 13.4208 8.11187 4.18975 1


Sensor Area mm^2 Relative Area
Full frame (35.8 x 23.9 mm) 855.62 30.86
APS-C (23.7 x 15.7 mm) 372.09 13.42
Four Thirds (17.3 x 13 mm) 224.90 8.11
1″ (13.2 x 8.8 mm) 116.16 4.19
1/2.33″ (6.08 x 4.56 mm) 27.72 1.00

Show-and-tell

We solve the problem of sorting on two keys with one ascending the other descending. This solution turns into a rather long thread as seen here.

Sorting on Two Keys

from:	Jimmy Gauvin <jimmy.gauvin@gmail.com> via forums.jsoftware.com 
to:	programming@jsoftware.com
date:	Jan 19, 2019, 11:18 AM
subject:	[Jprogramming] Sorting on two keys

Hi,

I need to sort on two keys, one descending the other ascending. ... Is there a better way to solve this ?

   ]t=:5 2$7 4 8 2 8 4 7 2 8 3
7 4
8 2
8 4
7 2
8 3
   ]tt=: t {~ /:1{"1 t
8 2
7 2
8 3
7 4
8 4
   ]tt {~ \:0{"1 tt
8 2
8 3
8 4
7 2
7 4

Thanks,

Jimmy

Roger replies:

Roger Hui rogerhui.canada@gmail.com / Jan 19, 2019, 11:41 AM

If the keys are numeric you can multiply the ascending column by 1 and the descending one by _1, and then apply /: .

   mat=: 5 2$7 4 8 2 8 4 7 2 8 3
   mat /: mat*"1 ]_1 1
8 2
8 3
8 4
7 2
7 4
   mat /: mat *"1 ]1 _1
7 4
7 2
8 4
8 3
8 2

Then R.E. Boss chimes in:

R.E. Boss r.e.boss@outlook.com / Jan 20, 2019, 7:02 AM

Also easy extendible to more columns, e.g. sorting ascending on first 2 columns and descending on last ones.

   [mat=.|:'abc'{~ 20 4 ?.@$3
accbacabbabcbbbbcbcb
cbbcbabaabcaaacababc
bbabbbacccaababbbbca
abcccbcacacbaacabacc

   /:~(2&{."1 <@(\:_2&{."1)/.])|: mat
+----+----+----+----+----+----+
|abca|acba|bacc|bcbc|cabb|cbcc|
|abbc|    |baca|bcbc|caab|cbbb|
|abac|    |baba|bcac|    |cbbb|
|    |    |baba|bcac|    |cbac|
|    |    |baba|    |    |    |
|    |    |baaa|    |    |    |
+----+----+----+----+----+----+

Ravelling finishes the job.


R.E. Boss

Roger responds:

Roger Hui rogerhui.canada@gmail.com/ Jan 21, 2019, 12:28 AM

As I said before, if the data is numeric, for each descending column, multiply by _1 and for each ascending column, multiply by 1, then apply /: to the result. This induces a "control array" having the same shape as a major cell of the argument, with a _1 for descending and a 1 for ascending.

What if the data is not all numeric? You can convert it to an order-equivalent numeric array by assigning to each atom an ordinal (an integer) which bears the same ordering relationship with the original atom, then solve numeric problem:

   ord =: /:~@, i.!.0 ]

That is, the ordinals obtain as the indices of the original array in the sorted list of the ravelled elements, using exact comparisons.

For example:

   x0=: <"0 ?19 $ 4
   x1=: (?19$2){'alpha';'beta'
   x2=: <"0 (?19$3){'abc'
   x3=: (?19$3){'able' ;'baker' ; 'charlie'; 'echo'

   mat =: x0,.x1,.x2,.x3

   ord mat
 9 60 26 52
11 45 19 38
11 60 26 38
11 45 26 52
 6 60 26 72
 6 60 19 52
 0 60 33 72
 0 60 26 52
 0 60 33 38
 0 60 19 38
11 45 19 52
11 45 19 52
 6 45 33 38
 0 60 26 72
 0 45 33 52
11 60 26 38
 9 60 19 52
11 60 33 72
11 45 19 38

Suppose mat is to be sorted ascending in columns 0 and 2 and descending in columns 1 and 3? The control array is 1 _1 1 _1, and:

   mat                     (/: 1 _1 1 _1*"1 ord mat) { mat
┌─┬─────┬─┬───────┐     ┌─┬─────┬─┬───────┐
│2│beta │b│baker  │     │0│beta │a│able   │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│3│alpha│a│able   │     │0│beta │b│charlie│
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│3│beta │b│able   │     │0│beta │b│baker  │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│3│alpha│b│baker  │     │0│beta │c│charlie│
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│1│beta │b│charlie│     │0│beta │c│able   │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│1│beta │a│baker  │     │0│alpha│c│baker  │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│0│beta │c│charlie│     │1│beta │a│baker  │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│0│beta │b│baker  │     │1│beta │b│charlie│
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│0│beta │c│able   │     │1│alpha│c│able   │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│0│beta │a│able   │     │2│beta │a│baker  │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│3│alpha│a│baker  │     │2│beta │b│baker  │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│3│alpha│a│baker  │     │3│beta │b│able   │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│1│alpha│c│able   │     │3│beta │b│able   │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│0│beta │b│charlie│     │3│beta │c│charlie│
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│0│alpha│c│baker  │     │3│alpha│a│baker  │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│3│beta │b│able   │     │3│alpha│a│baker  │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│2│beta │a│baker  │     │3│alpha│a│able   │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│3│beta │c│charlie│     │3│alpha│a│able   │
├─┼─────┼─┼───────┤     ├─┼─────┼─┼───────┤
│3│alpha│a│able   │     │3│alpha│b│baker  │
└─┴─────┴─┴───────┘     └─┴─────┴─┴───────┘

Mr. Boss has something else to say.

R.E. Boss r.e.boss@outlook.com / Jan 21, 2019, 7:36 AM

   > On Sat, Jan 19, 2019 at 8:40 AM Roger Hui <rogerhui.canada@gmail.com>
   > wrote:
   > > If the keys are numeric you can multiply the ascending column by 1 and the descending one by _1, and then apply /:  .

It is not enough to multiply with 1 or _1 for ascending or descending columns. You might have to reorder the columns as well.

Suppose the 3-column matrix x with

    |: mat=. ,/^:2 >{3#<i.3
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2
0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2

has to be sorted ascending by column 0, descending by column 2 and ascending by column 1, in that order.

Multiplying columns by 1 1 _1 and sorting would deliver

   |:1 1 _1( ]/: *"1 ) mat
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2
2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0

Whereas this is (the transpose of) what we want

   |: 1 1 _1( ]/: *"1)&.:(0 2 1&C."1) mat
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2
2 2 2 1 1 1 0 0 0 2 2 2 1 1 1 0 0 0 2 2 2 1 1 1 0 0 0   

Roger Hui rogerhui.canada@gmail.com / Jan 21, 2019, 12:10 PM

It's is possible that we have a different interpretation of what is the problem to be solved. My interpretation is the classic definition of lexicographic ordering. First, you order by column 0, resulting in groups of rows with identical values in column 0.

Then, within each group, you order by column 1, getting subgroups with identical values in columns 0 and 1. Then, within each subgroup, you order by column 1+k, getting subsubgroups with identical values in columns i.k. The "twist" is that each ordering in the process can be ascending or descending, to be specified separately for each column. I have seen system sort routines which deliver exactly this (ahem) sort of functionality.

Therefore, for mat=. ,/^:2 >{3#<i.3, the transposed result

   |: 1 1 _1 (] /: *"1 ) mat
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2
2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0

is exactly what I intended and consistent with my interpretation of the problem.

It's possible that your interpretation is what was asked in the original question posed by Jimmy Gauvin. No matter, I find my version an interesting problem and that's the one I am solving.

The original requestor thanks everyone:

Jimmy Gauvin jimmy.gauvin@gmail.com / Jan 21, 2019, 6:34 PM

HI,

thanks for all the answers, and the insights into J and sorting. The version applicable to my sorting needs is indeed the classic primary key, secondary key sort. And the R.E. Boss version is going into my toolbox.

Jimmy

But it's not over...

R.E. Boss r.e.boss@outlook.com / Jan 22, 2019, 5:30 AM

My intention was to give the most general solution to an actual problem.

If your mat variable denotes the columns to be sorted plus the way in which that should be done, like

0 3 2 1,:_1 1 _1 1

Then the (explicit) toolbox verb could be

   foo=:4 : ('''x1 x2''=.x' ; 'x2([/: *"1)&.:(x1&C."1)~ y')
   a ,.@;~&|:   (0 3 2 1,:_1 1 _1 1) foo a=.3#.^:_1 i.30
+-----------------------------------------------------------+
|1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|
|0 0 0 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2|
|0 0 0 2 2 2 1 1 1 0 0 0 2 2 2 1 1 1 0 0 0 2 2 2 1 1 1 0 0 0|
|0 1 2 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2|
+-----------------------------------------------------------+
|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1|
|0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 0 0 0|
|0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0|
|0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2|
+-----------------------------------------------------------+

Brian Schott schott.brian@gmail.com / Jan 23, 2019, 8:47 AM

RE,

Previously I learned via your code a use of C. that was eye-opening. This time, I learned via your code how a multi-x can be used in a one liner.

Very good.

R.E. Boss r.e.boss@outlook.com / Jan 23, 2019, 9:31 AM

Thanks Brian, I'm pleased to hear you enjoyed it.

Well, one can argue whether an explicit verb is a one-liner or not. At least it was too much work for me to fiddle out how to write this tacitly. We have high priests for that, haven't we?

BTW, it is more than a couple of years ago C. did not have an obverse.

R.E. Boss

Now someone else wants to add something:

Jose Mario Quintana jose.mario.quintana@gmail.com / Jan 23, 2019, 6:11 PM

> Well, one can argue whether an explicit verb is a one-liner or not.

Right, foo is not displayed as a one-liner,

   foo
4 : 0
'x1 x2'=.x
x2([/: *"1)&.:(x1&C."1)~ y
)

as opposed to,

   ( goo=. 4 : 'x2([/: *"1)&.:(x1&C."1)~ y [ ''x1 x2''=.x ' )
4 : 'x2([/: *"1)&.:(x1&C."1)~ y [ ''x1 x2''=.x '
   > At least it was too much work for me to fiddle out how to write this tacitly. We have high priests for that, haven't we?

Alas, no high priest has shown up yet. It seems to be too much work for me as well; particularly, because I regard myself as a lazy heretic anyway. Nevertheless, sometimes I spend some time thinking about certain things to avoid spending time thinking about certain things anymore. If I had to have a tacit version of foo, I probably would employ (;) instead of (,:) as a delimiter and use the following wicked version,

". noun define -. CRLF

hoo=. ((<<9 0 13),(<(<'X2'),(<,'('),(<,'['),(<'/:'),(<,'*'),(<,'"'),(<<(,'0');1),(<
,')'),(<'&.:'),(<'X1'),(<,'&'),(<'C.'),(<,'~'),<,'Y'),<(<0),(<2;3;4;5;6),(<8),(<9;10;11;5;6),(<12),<13)&((1&({::) ,^:(0:`(<'@.')) 2&({::))@:(<@:((0: 0&({::)@:] `(<@:(1&({::)@:]))`(2&({::)@:])} ])@:(3 0 1&{)) 1} ])@:(((#@:(1&({::)) ~: >@: (0&({::))) (([ # 3&({::)@:]) ,&:< [ <@:# >@:(0&({::))@:]) ]) 3 0} ])@:(, <))@ :(<@:((,'0') ,&:< ])&.>)@:([ , <@:])
)

Yes, it is displayed as a pretty long one-liner (admittedly, "a pretty long one-liner" is, in some sense, an oxymoron), … Of course, I did not write hoo directly; instead, I just wrote the less cryptic (to me anyway),

   erase'X1 X2 Y'  NB. (just in case)

   hoo=. [: X1 X2 Y 'X2([/: *"1)&.:(X1&C."1)~ Y' xi o ([ , <y)

after running the J Wicked Toolkit and I amended its faulty linear representation to repair the damage caused by the resistant bug,

   ^:(0:`(<'@.'))
^:(0:`@.)

(Beware, wicked entities run on j807; but, I am afraid, their days might be counted.)

PS. I am sure a willing high priest can write a neat orthodox tacit version instead.

R.E. Boss r.e.boss@outlook.com / Jan 25, 2019, 5:42 AM

Your solution is beyond my capacity to comprehend, or to appreciate.

My explicit verb could easily be turned in a one-liner by

   foo=: 4 :  '({:x)([/: *"1)&.:(({.x)&C."1)~ y'
   |:(0 3 1 2,:_1 1 _1 1) foo a=.3#.^:_1 i.30
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2 0 0 0 1 1 1 2 2 2
0 0 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0 2 1 0
0 1 2 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2

I decided to test my craftmanship on tacitness and, after quite some thinking, came up with

 
   foo_tct=: ([({.@[,{:@[(]/: *"1 )}.@]) &.:(({., {.C."1 }.) :. ({.C.^:(_1)"1 }.)) (,~{.)~)
   (0 3 1 2,:_1 1 _1 1) (foo-: foo_tct) a
1

Once more I was remembered to the fact that in the under construction, u&.v and u&.:v , v and its inverse are always applied monadically, v to the left and right parameters, and its inverse to the result of u. For that reason I had to add the first item at the left to the noun at the right. The inverse I also had to define properly.

R.E. Boss

Jose Mario Quintana jose.mario.quintana@gmail.com / Jan 25, 2019, 6:45 PM

   > Your solution is beyond my capacity to comprehend, or to appreciate.

One reason, among other reasons, for using the (tacit wicked) adverb xi is that it often can easily produce tacit verbs when the adverb (13 :) cannot. I do not really have to know how the original verb works; for instance, a tacit counterpart for your new version of

foo=: 4 :  '({:x)([/: *"1)&.:(({.x)&C."1)~ y'

can be produced as follows,

goo_tct=. [: X Y '({:X)([/: *"1)&.:(({.X)&C."1)~ Y' xi o ;

I did not have to spend any time thinking about the tacit conversion (did I mention I am lazy?). The products of xi are usually competitive (particularly for big arguments); apparently, the case at hand is not an exception.

   > I decided to test my craftmanship on tacitness and, after quite some thinking, came up with
   > foo_tct=: ([ ({.@[, {:@[(]/: *"1 ) }.@]) &.:(({., {.C."1 }.) :.({.C.^:(_1)"1 }.)) (,~{.)~)

I knew a willing high priest could write it. ;)

   stp 666
(0 3 1 2,:_1 1 _1 1) foo     a
(0 3 1 2,:_1 1 _1 1) foo_tct a
(0 3 1 2,:_1 1 _1 1) goo_tct a
)
┌──────────────────────────────┬─────┬───────────┬────────────┐
│Sentence                      │Space│Time       │Space * Time│
├──────────────────────────────┼─────┼───────────┼────────────┤
│(0 3 1 2,:_1 1 _1 1) foo     a│18304│6.58107e_5 │1.2046      │
├──────────────────────────────┼─────┼───────────┼────────────┤
│(0 3 1 2,:_1 1 _1 1) foo_tct a│23744│0.000370558│8.79853     │
├──────────────────────────────┼─────┼───────────┼────────────┤
│(0 3 1 2,:_1 1 _1 1) goo_tct a│23360│9.4704e_5  │2.21229     │
└──────────────────────────────┴─────┴───────────┴────────────┘

C. or "Ccapdot"

Some of the solutions above use C. which is not a common verb, so here is information about it [ https://code.jsoftware.com/wiki/Vocabulary/ccapdot from the J vocabulary].

Vocabulary/ccapdot

C. y Cycle-Direct

Converts the permutation y between direct and cycle representations.

   ]cycle =: C. 1 2 0 5 4 3  NB. Convert to cycle form
+-----+-+---+
|2 0 1|4|5 3|
+-----+-+---+
   C. cycle                  NB. Convert back to direct form
1 2 0 5 4 3

A permutation of an array a is an array b containing the same items as a but possibly in a different order. The relation between the ordering of the items of a and b is called a permutation, and the action of creating bfrom a is called applying the permutation to a.

The direct representation, d, of a permutation, lists for each index i in b the index in a that moved to position i. In the example above, item 1 in a moves to be item 0 of b, item 2 of a moves to be item 1 of b, item 0 of a to item 2 of b, and so on. A cycle representation c of a permutation breaks the permutation into cycles where each listed item moves to the position of the next number in the cycle, with the last item in the cycle going to the first position in the cycle. In the example above, the first cycle (2 0 1) indicates that the item in position 2 moves to position 0, the item in position 0 to position 1, and the item in position 1 to position 2. The cycle (5 3) indicates that items 5 and 3 exchange places, and the cycle (4) indicates that item 4 does not move. ________________________________________

Common Uses

1. Find the cycle form of a permutation, as above. In standard math notation the cycles are represented in parentheses, as

1 2 0 5 4 3 <--> (2 0 1)(4)(5 3)

2. Examine the cycle structure of a given permutation p.

The cycle representation reveals many of the properties of p to a group theorist. Moreover the cycle representation is one of the most compact and convenient forms for handling permutations in books and hand-calculations.

More Information

1. The cycle representation of a permutation is not unique: the cycles may be presented in any order and each cycle may start with any of its members.

Cycle representations produced by C. y are put into a standard form as follows:

• The largest index in each cycle comes first
• The cycles are sorted into ascending order of their largest index

This ordering is expressed in canoncycle below. To use a different canonical form, modify canoncycle.

   NB. verb to put a cyclic representation into canonical order
   NB. There must be no omitted or negative indexes
   canoncycle =: (/: {.@>) @: (,@(|.~ (i. >./))&.>)

   ]permc =: 6;0 5 1;2 3 4   NB. A cycle form
+-+-----+-----+
|6|0 5 1|2 3 4|
+-+-----+-----+
   canoncycle permc          NB. canonical form
+-----+-----+-+
|4 2 3|5 1 0|6|
+-----+-----+-+
   C. C. permc               NB. J produces canonical form
+-----+-----+-+
|4 2 3|5 1 0|6|
+-----+-----+-+

2. The length n of a permutation y is n =. >: >./;y , i.e., one more than the largest value in y. This value must be positive. Any negative index i in y, whether in a box or not, is processed as i+n . In other words, negative values count back from the end, just like negative array indexing.

   C. C. _3 1 2   NB. n = >:2 = 3
0 1 2

3. A completely-described permutation of length n includes each value of i. n exactly once. If some of those values are omitted, default values are assumed.

• for permutations y in direct form, omitted values are prepended to the beginning of y before the conversion to cycle form.
• for permutations y in cycle form, omitted values are assumed to represent cycles of length 1, in other words, positions that are unaffected by the permutation.

To see the complete form of an incomplete permutation, apply C. y twice, which will convert the permutation to canonical form in its original representation:

   C. C. 4 2 6    NB. incomplete direct form: omitted values move to front
0 1 3 5 4 2 6
   C. C. 1 3;2 5  NB. incomplete cycle form: omitted values do not move
+-+---+-+---+
|0|3 1|4|5 2|
+-+---+-+---+

4. If, after the conversion of originally negative values, y has duplicate values, or any values less than 0 or greater than or equal to the length n of the permutation, an error is signaled.

________________________________________

Details

1. If y is an empty numeric or character list, an error is signaled. If y is an empty list of boxes, the result is an empty numeric list (i.e. an empty permutation).

Advanced topics

We compare examples of two different variations of coding - one where we look at basic C code versus object-oriented C code and another where we look at procedural APL versus "denotative" (also known as "functional") code.

Compare Class Implementation to Normal Code

In a StackOverflow discussion (https://stackoverflow.com/questions/865668/how-to-parse-command-line-arguments-in-c) on how to parse command-line arguments in C++, there was a suggestion for code to parse "simple command line options" that was followed by version of the same code but encapsulated in a class. How do the two versions compare? I have edited the answers slightly to reduce white-space.

Basic Version Class Encapsulation
  #include <algorithm>
  char* getCmdOption(char ** begin, char ** end, const std::string & option)
  {   char ** itr = std::find(begin, end, option);
      if (itr != end && ++itr != end)
      {   return *itr;
      }
      return 0;
  }
  bool cmdOptionExists(char** begin, char** end, const std::string& option)
  {   return std::find(begin, end, option) != end;
  }
  int main(int argc, char * argv[])
  {   if(cmdOptionExists(argv, argv+argc, "-h"))
      {   // Do stuff
      }
      char * filename = getCmdOption(argv, argv + argc, "-f");
      if (filename)
      {   // Do interesting things
      }
      return 0;
  }
   class InputParser
   {   public:
          InputParser (int &argc, char **argv)
          {   for (int i=1; i < argc; ++i) this->tokens.push_back(std::string(argv[i]));
          }
          const std::string& getCmdOption(const std::string &option) const
          {   std::vector<std::string>::const_iterator itr;
              itr =  std::find(this->tokens.begin(), this->tokens.end(), option);
              if (itr != this->tokens.end() && ++itr != this->tokens.end())
              {   return *itr;
              }
             static const std::string empty_string("");
             return empty_string;
          }
          bool cmdOptionExists(const std::string &option) const
          {   return std::find(this->tokens.begin(), this->tokens.end(), option) != this->tokens.end();
          }
      private:
          std::vector <std::string> tokens;
  };
  int main(int argc, char **argv)
  {   InputParser input(argc, argv);
      if(input.cmdOptionExists("-h"))
      {   // Do stuff
      }
      const std::string &filename = input.getCmdOption("-f");
      if (!filename.empty())
      {   // Do interesting things ...
      }
      return 0;
  }

We see how the object-oriented version is far more elaborate with no obvious benefit.

An Analogous(?) Distinction in APL: Procedural versus Denotative

The late, great John Scholes says that the introduction of the “at” operator in APL removed the only case where he still needed to use procedural code: for indexed assignment. He states that going from procedural to denotative requires a change of mindset. “Procedural programming is a lot about the representation and manipulation of state…but, for a subset of programming, you can switch to a much pleasanter world where you just talk about definitions and you can forget about time and sequencing.”

The example he gives of this contrast in some code is the following pair of function to find the shortest path through a graph:

Finding the shortest path-Procedural vs Denotative coding.jpg

He opines that “denotative” is a slightly more general term than “functional”.

Procedural vs denotative - path through a graph.jpg

  g pathP 2 1     NB. For graph “g”, find the path from node 2 to node 1 (origin 1).

These are virtually the same except that the indexed assignment is replaced by a use of the “at” operator, so he can replace a loop with a recursion: think of defining factorial by the recursive definition: !n <-> n * !n-1. The advantage of the denotative version is that we could eliminate the temporary name “tree”: graph reduction.

Learning and Teaching J

We look at an essay about how social media like Facebook helps people prefer opinion to fact.

The Science Behind Why Your Facebook Friends Ignore Facts

Cognitive bias and you

Mike Fishbein / Oct 17, 2016

I’ve long believed that humans are rational beings. That is to say, we use logic and evidence to make decisions and determine what’s true. As it turns out, a wealth of cognitive research proves that I was decidedly wrong. We live in a world where more information is flooding our brains than ever before. Advertisers have long battled for our attention. But now, software developers battle for it too, and then sell it back to the advertisers. The more effectively Google, Twitter, and Medium can capture our attention, the more money they make.

If we didn’t filter almost all of the information that we receive, we’d be completely overwhelmed. That’s why our brains use “shortcuts” to pick out the bits of information that are most likely to be useful. And by useful, I don’t necessarily mean true. By useful, I simply mean that the information will help you stay alive.

________________________________________

You may find yourself wondering: Why is the world so divided on religion and politics? Why do people support Donald Trump? Or Hillary Clinton? Why can’t I convince my friend to change his mind?

Below, I’ll share how our brains deal with information overload — and the associated cognitive biases that prevent us from correctly understanding the facts.

The Availability Heuristic: Believing What’s Top of Mind

The availability heuristic is a mental shortcut that relies on immediate examples that come to mind to determine truth or falsehood. It posits that when it comes time to make a decision, we leverage what is already top of mind. We give greater credence to this information and tend to overestimate the probability and likelihood of similar things happening in the future.

This shortcut is helpful in decision-making because we often lack the time or energy to investigate complex issues in greater depth. The availability heuristic allows people to arrive at a conclusion more quickly. However, like other shortcuts, it can lead us astray. Of course, just because something is in our mind doesn’t mean it’s true.

For example, after Donald Trump described Hillary Clinton as “crooked,” we were primed to interpret her behavior as such. The interpretation doesn’t necessarily mean she’s not crooked, it just means that our brains are more likely to come to that conclusion because it’s easier than evaluating the situation from scratch.

Attentional Bias: Believing What We Pay Attention To

Attentional bias is the tendency for our conclusions to be affected by our recurring thoughts. Furthermore, attentional bias predicts that attention will be preferentially allocated towards threatening, rather than neutral or positive, stimuli.

If you think what you see is the whole story, you’re displaying attentional bias. To arrive at a more accurate conclusion, you also need to consider the things you don’t see.

For example, when someone looks at only one, or a few, economic data points and then determines that the economy is strong or that the government is doing a great job, he is forgoing the time and energy necessary to gain a more complete picture.

The Illusory Truth Effect: Believing What’s Repeated

Repetition is another way that misconceptions can enter our knowledge base. Per The Illusory Truth Effect, repeated statements are easier to process, and subsequently perceived to be more truthful than new statements. Our brain spends less time and effort on processing information that’s been repeated and takes it as truth simply because it’s familiar.

The reverse is also true: people interpret new information with skepticism and distrust.

Take the topic of nutrition. For decades, we’ve been told that eating fat is unhealthy. Despite recent studies proving the contrary, our diets continue to be high in sugar and processed carbohydrates.

It doesn’t always matter what we’re told — a truth or a lie — we’re more likely to believe it if it’s repeated. It’s the frequency, not just the reality, that matters.

The Mere Exposure Effect: Believing What’s Familiar

Not only is repeated exposure more likely to make us believe something, it’s more likely to make us form a favorable opinion of it. Per The Mere-exposure Effect, also known as the familiarity principle, we tend to like things that are familiar to us.

Repeated exposure of a stimulus increases perceptual fluency, which is the ease with which information can be processed. Perceptual fluency, in turn, increases positive sentiment. Familiar things require less effort to process and that feeling of ease signals truth.

We are attracted to familiar people because we consider them to be safe and unlikely to cause harm. We can even adapt to like things that are objectively unpleasant, such as when former prisoners miss prison.

________________________________________

When trying to make an important decision, have you ever come short of considering all information and possibilities? While we might like to think that we take all the facts into consideration, the reality is that we often overlook some information. If we fact checked anything and everything that crossed our minds, we’d be paralyzed. By using the “shortcuts” above — rather than coming to our own conclusions using reason and evidence — we may be wrong some of the time. However, determining what’s true is not always necessary to survive. Sometimes it’s more effective to make faster decisions and err on the side of safety.

Ease trumps truth

Imagine if a CEO couldn’t trust his marketing team to analyze data. The CEO wouldn’t be able to focus on keeping the company alive and growing it. He’d be stuck in the minutiae of marketing analytics. Similarly, our brains have to sacrifice accuracy to increase the chances of surviving and reproducing.

Humans across the world have come to different conclusions about important issues like religion and politics. Logically then, most of them must be wrong. However most people are not dying as a result of believing in the “wrong” religion.

The fact that we are so divided on the election is further evidence that we are not completely rational. Even if one side was “right,” that would mean that about 50% of the population was wrong. If we were even predominately rational, wouldn’t at least a more significant portion of the population be on one side?

You might say “ah, but the two-party system doesn’t make any sense.” But we have a two party system — which doesn’t make sense. That’s further evidence to my point!

If people were rational, there would be no need for emotional advertising campaigns or political speeches, we would simply educate people about the facts.

________________________________________

When I first realized that people are irrational, I was confused and frustrated. I felt hopeless. I wished things were different. But that only caused anxiety.

Accepting that most people — myself included — are irrational most of the time actually eased the stress. Now I don’t have to wonder about why my Facebook friends believe half of the crap that they share and like, why they endorse a particular political candidate that I don’t agree with, or why they believe in their respective religion.

We live in an incredibly complex world. Familiar information is easier to understand and repeat. The cognitive biases above can help us make decisions faster and therefore stay alive in uncertain environments, but they don’t necessarily help us find truth. In a weird way, being irrational actually makes sense.

Miscellaneous

An amusing article we recently noticed...

Hipster Offended

[From https://www.dpreview.com/news/7021408195/hipster-offended-after-mistaking-himself-for-hipster-in-study-about-lookalike-hipsters]

Hipster offended after mistaking himself for hipster in study about lookalike hipsters

Published Mar 8, 2019 | Brittany Hillen

Hipster offended - photo of hipster.JPG

Gideon Lichfield, editor-in-Chief of MIT Technology Review, recounted a hilarious story of mistaken identity on Twitter this week. According to Lichfield, the publication received an angry email from a man who accused the site of using his portrait without permission to illustrate an article about hipsters who all look the same. The problem? This unnamed complainant wasn't the man in the image.

The issue began when MIT Technology Review published an article detailing a study called The Hipster Effect: When Anti-Conformists All Look The Same. The article includes a properly licensed header image depicting a prototypical hipster sourced from Getty Images, but the angry email writer didn't know that, instead believing it was an image of himself.

Tweet about offended hipster.JPG

The publication's Creative Director Eric Mongeon contacted Getty Images to verify the photo's model release, and that's when the mystery was solved:

Hipster offended - follow-up.JPG

Lichfield's amusing Twitter story seemingly underscored the study's premise, but sadly it didn't include an image of the email writer for comparison.