Decreasing sequences
It occurred to me that I could think of two ways to generate a decreasing sequence. The built-in i.
will do this:
i. _7
6 5 4 3 2 1 0
But I could see a way to do it with self-reference $:
or with iterate ^:
:
(<:^:*^:a:) 7
7 6 5 4 3 2 1 0
This essentially says “iterate gathering results” ^:a:
“while non-zero” ^:*
“decrement” <:
. This differs slightly from i. _7
because it includes the number 7, but whatever.
The self-reference $:
method is a little longer:
0:`(, $:@<:) @.* 7
7 6 5 4 3 2 1 0
Like any recursive function, we need a base case and an inductive case. Sentences like
f`g@.t
in J give you case analysis, so a sentence like:
0:`f @.*
is a strong clue that your base case maps 0 to 0 and runs all positive numbers through f
, and that’s what’s happening here. So the next step is understanding , $:@<:
. This is about as simple as self-reference can get: we’re making a hook (it means the same as ] , $:@<:
if forks make more sense to you than hooks) basically using ,
to append the current value with the result of the recursive call. $:@<:
says “apply myself after decrementing the argument”.
This suggests an obvious way to get the increasing list, by just flipping around the arguments to ,
append:
0:`($:@<: , ]) @.* 7
0 1 2 3 4 5 6 7
I’m sure the self-reference version is worse in performance terms, but there isn’t as straightforward a way to flip it around like this, so this counts as an advantage here.
Detecting palindromes
This is one thing where Prolog usually has a significant advantage over other languages, because you can make the relationship between palindromes and reflection explicit:
palindrome(X) :- reverse(X, X).
However, J is still able to beat this:
palindrome =: -: |.
Match the value with its reflection.