It would be great if someone could translate that into J, then I might have a chance of understanding it properly.
Code summary:
r =. (3 3 $ i. 9) e. 1 2 3 4 7
R =. _1 |. _2 |."1 (5 7 {. r)
RR =. 15 35 {. _10 _20 {. R
life =. verb : '+./ > (1;y) *.each 3 4 =each +each/ +each/ 1 0 _1 |.each/ 1 0 _1 |."1 each <y'
gen =. dyad : 'life ^: y x'
The 20th generation: (RR gen 20) { '.X'
...................................
...................................
...................................
...................................
.........X....XXX..................
........XX.....XX..................
.......XX.....XX...................
........X.X...X.X..................
.........XX....XXXX................
..........X...X..XX................
..............X.XX.................
..............XXX..................
...................................
...................................
...................................
Transcript of the whole talk with line by line translation here: https://dpaste.de/OoEM/raw (expires in 7 days).APL, rather than J, but here's a beautiful Prime Numbers up to 20 example:
(~R∊(R∘.×R))/R←1↓⍳20
Reading right to left, iota 20 makes numbers 1 through 20 inclusive, 1 drop takes that list as an argument and removes the first element, R left arrow takes that shorter list as an argument and stores the numbers 2 through 20 into variable R.In the nested parens, the outer product multiplication pattern (R___R) makes a multiplication table of the vector R against itself, and because we dropped 1 from the list we avoid all the 1xN and Nx1 pairs so it's a table of composite numbers. Then outer parens R epsilon compares each item in R with the matrix of composite numbers and generates a boolean result vector the same size and shape as R, but each input number has become 1 if it was found as a composite number, 0 if it wasn't (aka prime). Negate that bitmask so 1 indicates where a prime number was in the original R numbers, and use / to filter (reduce) the original list to pick those out.
Primes: Numbers 2..N which aren't members of all the products of 2..N.
No explicit loops, no if/else branching, no proliferation of names for working arrays, no need to wrap it in a function, give the function a name, document the function parameters and their assumptions. And even though it is N-squared runtime, it's short enough that an interpreter could pick out that pattern in code and implement it faster behind the scenes, if that was beneficial, without forcing the programmer to interrupt neat code to appease the machine beneath.
I can't APL or J, but I transliterate it to J as:
(-. R e. ; R*/ R=: 2 }. i. 20) # R
J starts counting at 0 so this drops two numbers from the list. (Yes, J has p: for making Prime numbers).