Subject: roman and arabic - some fun(ctions)
From: richard.levine@canrem.com (Richard Levine)
Date: Fri, 11 Aug 95 03:19:00 -0500
Organization: CRS Online  (Toronto, Ontario)

Here are the results of an exercise using some simple but cute
functions to learn J.  The results were personally quite
rewarding and may be of interest.

I did not "catch on" to J quickly.  However, that is a personal
statement about me, not about J.  My goal has been to become
familiar with large parts of J.  So, considering the richness
of the language and my unfamiliarity with the development of J
concepts (going back many years), I feel that the time has not
been inappropriately long.  (Even a restricted subset makes for
a very powerful programming language, but many among us insist
on learning the whole thing, which is not unreasonable.)  Also,
I feel my familiarity and years of "internalizing" APL in
various dialects has made it more difficult (a situation that
has in fact been reported by others.)  The following exercise
turned out unexpectedly to be a really helpful learning
exercise.

As an exercise in learning J, I translated two simple functions
taken from the Toronto Toolkit, from APL (standard APL). One
function returns the roman numeral equivalent of an arabic
number, the other is the "inverse", giving the arabic
equivalent of a roman numeral.

First I translated the functions.  They were simple functions
of several lines.  (By the way, has anyone made a little
translation table of APL equivalents of the common functions
and idioms for use in translating from APL to J?  Studies have
shown that certain functions and idioms are very common in APL
functions --- the 80/20 "rule".)  If anyone wants to see mine,
send me a line.

For those "translation hackers" who love horror stories about
rewrites, I will mention that even in these small functions I
found some "wierd" APL code.  For example, what do you think
this meant?

(in origin 1)(actually it doesn't matter)
(a,0)[1+ {iota} {rho} a]

If you guessed the following ...

1 {drop} a,0

... then you guessed what I guessed!!  I wonder if I'll ever
find out how that got in there!  It worked, though.

Anyway, the J functions were straightforward translations of
the algorithms, allowing for changing from origin 1 to origin
0, removing "wierd" phrases (see above), and removing some
parameter checking (for simplicity).

   roman 16
xvi
   roman 1995
mcmxcv
   arabic 'xvi'
16
   arabic 'mcmxcv'
1995

Now the original functions expected single numbers only, no
lists or matrices.
Then suddenly I realized I could use "the power of J".  All
of a sudden the stuff I was learning about rank operator and
the various composition conjunctions (& and @) were useful!!
I could easily apply the functions (now called verbs) to any
array!

   9!:7 '+++++++++|-'
   roman"0 i.10

i
ii
iii
iv
v
vi
vii
viii
ix

   NB. Let's box each result for a neat one-line display.

   <@roman"0 (10+i.10)
+-+--+---+----+---+--+---+----+-----+---+
|x|xi|xii|xiii|xiv|xv|xvi|xvii|xviii|xix|
+-+--+---+----+---+--+---+----+-----+---+

   NB. Same idea for several multi-character arguments.

   each =. &.>
   arabic each 'xvi';'xxx';'mcmxcv'
+--+--+----+
|16|30|1995|
+--+--+----+

   NB. This next part took a little experimentation to
   NB. figure out how to return an unboxed result
   NB. There are other ways but I wanted to play with
   NB. the power of adverb operators.

   (arabic &: > " 0) 'xvi';'xxx';'mcmxcv'
16 30 1995

   every =. 1 : 'x. &: > " 0'
   arabic every 'xvi';'xxx';'mcmxcv'
16 30 1995

   NB. Then I got another idea. I mentionned I had always
   NB. considered "roman" and "arabic" as inverses ...

   roman 2001
mmi
   arabic roman 2001
2001
   roman arabic 'mi'
mi

   NB. Now I could show this using the
   NB. Power conjunction (operator).

   NB. Define a function "roman" with inverse "arabic"

   f =. roman :. arabic
   f 16
xvi

   NB. The power _1 is the inverse function, as is usual using
   NB. power notation.

   f^:_1 'xvi'
16
   f^:_1 f 16
16

   NB. This is fun.  I like J.

   NB. The text of the functions.

   roman
+-+-+---------------------------------------------------------+
|3|:|NB. returns roman numeral equivalent for arabic number y.|
| | |NB. highest number in domain is 3999                     |
| | |antibase =. #:                                           |
| | |y =. , y.                                                |
| | |m =. 3 3 3 3,1 3 3 3,1 1 3 3,1 1 1 3,1 0 3 3,0 3 3 3     |
| | |m =. 10 4 $ m, 0 1 3 3, 0 1 1 3, 0 1 1 1, 1 _1 3 3       |
| | |a =. ,(10 10 10 10 antibase y){m                         |
| | |(_1 + (a ~: 3) # a + 2 * <. 0.25 * i. 16) { 'mdclxvi'    |
+-+-+---------------------------------------------------------+
   arabic
+-+-+---------------------------------------------------------+
|3|:|NB. returns arabic number equivalent for roman numeral y.|
| | |NB. arabic is type numeric (base 10), roman is character |
| | |gte  =. >:   NB. (greater than or equal)                 |
| | |drop =. }.                                               |
| | |a =. ('ivxlcdm' i. y.) { 1 5 10 50 100 500 1000          |
| | |+/ a * _1 + 2 * a gte 1 drop a,0                         |
+-+-+---------------------------------------------------------+

--RL
