Fifty Shades of J/Chapter 18
Table of Contents ... Glossary ... Previous Chapter ... Next Chapter
Principal Topics
- ] (right) /. (infix) \. (suffix) /: (grade up) ` (gerund) list constructor, statement separator, zigzag matrix.
The problem with J isβ¦
β¦ identifying instantly the various parts of speech. Even in the second or so it took you to read this sentence you subconsciously identified its form and shape because you recognised βproblemβ, βpartβ, βspeechβ as nouns, βisβ as a verb, βinstantlyβ as an adverb and so on. In linguistic terms you sorted out the syntax with scarcely a thought, deferring for the moment whether or not you were going to bother working out the semantics.
By contrast, in J the parts of speech to which the various symbols belong are not immediately obvious. Take for example a discussion on the J programming forum concerning how to rearrange the square matrix i.n n in zig-zag format, so
zigzag=.($ /:@:;@:(|.&.>`]/.)@:(</.)@:i.)@:(2&#) zigzag 4 0 1 5 6 2 4 7 12 3 8 11 13 9 10 14 15
The above one-line solution submitted by Henry Rich states the solution admirably, but its structure and meaning is clear only to the super-expert.
J is best understood in terms of processing lists, which is what goes on behind the scenes anyway. Verbs like transpose which operate at the surface level on objects of higher dimensions than lists are more accurately conceived as list constructors, in other words the verb transpose is not so much βswitch matrix rows and columnsβ as βconstruct a new list of lists from a given list of equal length listsβ. There is no problem in extending this idea to dyadic transpose, that is to lists of lists of lists β¦ ad infinitum.
Adverbs such as / and /. make βstraightforwardβ verbs like < and +/ into list constructors. For example
</.i.4 4 βββ¬ββββ¬ββββββ¬βββββββββ¬ββββββββ¬ββββββ¬βββ β0β1 4β2 5 8β3 6 9 12β7 10 13β11 14β15β βββ΄ββββ΄ββββββ΄βββββββββ΄ββββββββ΄ββββββ΄βββ
constructs a 7-list systematically from the elements of four 4-lists, sometimes with dimensionality (rank) being reduced in the process
+//.i.4 4 NB. one 7-list from four 4-lists 0 5 15 30 30 25 15 (<0 1)|:i.4 4 NB. one 4-list from four 4-lists 0 5 10 15
An interesting verb which can bring about list construction is ] (right) which it is easy to dismiss trivially as a βdo-nothingβ sort of verb, or at least βdeliver the right argument and do nothing with itβ.
2]i.3 3 0 1 2 3 4 5 6 7 8
However, if qualified with the prefix adverb
]\i.3 0 0 0 0 1 0 0 1 2
it gives successive sublists (with fill) constructed either forwards from a simple numeric, or backwards :
(]\.)i.3 0 1 2 1 2 0 2 0 0
or as boxed lists suppressing the fill items :
(<@:]\)i.3 βββ¬ββββ¬ββββββ β0β0 1β0 1 2β βββ΄ββββ΄ββββββ
The same effects could be achieved by replacing ] with > or + or many other verbs.
Ken Iverson used J to suggest that the numeracy functions of the brain are more closely allied to the literacy ones than is popularly believed, the first step being to overcome the syntax barrier. Part of the problem is that whereas statement separators tend to stand out in other languages, @: meaning βafterβ acts in J like a statement separator as in this@:that@:thenext, but is often harder to pick out in a blitz of non=alphabetic characters. In the light of this look again at :
zigzag=.($ /:@:;@:(|.&.>`]/.)@:(</.)@:i.)@:(2&#)
in which it is difficult at a glance to pick out the all-important @: symbols. As a first step in understanding construct lists of the leading diagonals of i.n n and consolidate the procedure as
diagilist=.monad : '</.i.y,y' diagilist 4 βββ¬ββββ¬ββββββ¬βββββββββ¬ββββββββ¬ββββββ¬βββ β0β1 4β2 5 8β3 6 9 12β7 10 13β11 14β15β βββ΄ββββ΄ββββββ΄βββββββββ΄ββββββββ΄ββββββ΄βββ
Another important indicator which is easy not to spot is the gerund marker, that is the dash in the middle. The adverb /. activates the gerund as in
(+`-/.)4 5 6 7 4 _5 6 _7
and so a fuller parenthesising is ((|.&.>)`(])/.), that is the two parts of the gerund are |.&. and ] and not |.&. and ]/. , so define
reversealt=.|.each`] zz=.(reversealt/.)@:diagilist ,zz 4 βββ¬ββββ¬ββββββ¬βββββββββ¬ββββββββ¬ββββββ¬βββ β0β1 4β8 5 2β3 6 9 12β13 10 7β11 14β15β βββ΄ββββ΄ββββββ΄βββββββββ΄ββββββββ΄ββββββ΄βββ
or, removing the boxes
;zz 4 0 1 4 8 5 2 3 6 9 12 13 10 7 11 14 15
Alternate diagonals have been reversed, and the problem now is to reverse the diagonalisation. Here is where an ingenious and insightful verb comes in. For any permutation p of i.n the following applies :
p=.16?16 (/:p){p 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
that is grade-up restores i.n from any of its permutations. Now ;zz 4 as shown above is a permutation of i.16 whose grade-up, just like any other permutation, puts the numbers of i.16 back into natural order, which is exactly what is required in order to display the zigzag matrix in its conventional 4 by 4 format. Thus define a verb :
gradeupraze=./:@; zz=.gradeupraze@:(reversealt/.)@:diagilist zz 4 0 1 5 6 2 4 7 12 3 8 11 13 9 10 14 15
and finally reshape this as n by n :
zigzag=.(2&#)$gradeupraze@:(reversealt/.)@:diagilist zigzag 4 0 1 5 6 2 4 7 12 3 8 11 13 9 10 14 15
The sophistication of the J involved cannot be disguised, but using pseudo-English to break up the primitive symbols greatly helps comprehensibility. It also helps distinguish the more subtle thinking about permutations and grade-up from the otherwise relatively mundane data structuring operations.
Solving programming exercises of this sort often lead to further generalisations. For example consider how restructuring of the 4 by 4 matrix might be achieved :
0 7 8 15 1 6 9 14 2 5 10 13 3 4 11 12
udilist standing for βup and down integer-listβ is a list constructor analogous to diagilist :
udilist=.monad : '<"1 |:i.y,y' udilist 4 ββββββββββ¬βββββββββ¬ββββββββββ¬ββββββββββ β0 4 8 12β1 5 9 13β2 6 10 14β3 7 11 15β ββββββββββ΄βββββββββ΄ββββββββββ΄ββββββββββ
Now instead of the first, third, and so on list being reversed it is now the second, fourth β¦, so define the gerund
revalt=.]`(|.each)
and finally retread the ground of zigzag :
updown=.(2&#)$gradeupraze@:(revalt/.)@udilist updown 4 0 7 8 15 1 6 9 14 2 5 10 13 3 4 11 12
If the start point is required to be in the south-west corner, replace revalt with reversealt.
Code Summary
diagilist=: monad : '</.i.y,y' reversealt=: |.each`] gradupraze=: /:@; zigzag=: (2&#)$gradupraze@:(reversealt/.)@:diagilist udilist=: monad : '<"1 |:i.y,y' revalt=: ]`(|.each) updown=: (2&#)$gradupraze@:(revalt/.)@udilist