Next thing to figure out is how it does this. It turns out, after some
experimenting, that the best way of reading this is to go through from
right to left and figure out what it all does. All the functions we're
looking at end up being applied in a monadic fashion - which means
something completely different in J than in Haskell - here it means
that the function gets applied to a single argument. So, here goes:
i. n lists the first n integers, starting at 0. So i. 100 is
the 1x100 matrix containing 0, 1, 2, ..., 99.
>:, when applied monadically, increments each element it sees by
one. So >: i. 100 is the 1x100 matrix containing 1, 2, 3, ...,
100.
q: yields a prime factorization of the integers it sees. So from
q: >: i. 100 we get a matrix where each row carries the primes
dividing the row number, with 0 padding at the end.
Then we see the one dyadic (as opposed to monadic) application in
this program. 5 = mtx yields a matrix of the same shape as mtx,
but with a 1 whenever the corresponding entry is a 5, and 0 otherwise.
So 5 = q: >: i. 100 picks out the entries in all the prime
factorizations that are equal to 5.
Then ,. This is one of two complementary operators to reshape
matrices. , gets us an 1xn matrix with the same entries, read row
by row, from left to right, as we started with - whereas n m $ mtx
takes the matrix in mtx and builds an nxm matrix out of it. Thus,
, 5 = q: >: i. 100 flattens out the matrix with the 0 and 1 we got
out above.
And finally, +/ is an example of a J adverb being used. + is
a dyadic function corresponding to, as expected, usual addition. /
is a monadic adverb that takes a dyadic function, and inserts it
between all the elements in the following list. This is essentially
identical to the Haskell call foldr. So +/ is more commonly
known as "sum". And thus, +/ , 5 = q: >: i. 100 sums up the 0s and
1s produced by picking out all the entries in the prime factorization
matrix that are equal to 5, after flattening the matrix. Or, in other
words, counts the 1 entries. Which is the same as counting the number
of 5s in the prime factorizations of all the integers between 1 and
100.
Note that if we skipped the flattening step given by , then the
application of +/ would have just summed each column in the
matrix. So, we would have needed to apply it again to get the total
tally.