Here's my solution to the Zark numbers-to-words puzzle. #IO is assumed to be 1, the APL plain vanilla.

The bottom-level function, SPELL2, uses global tables SPELLTAB1 and SPELLTAB2 to spell a one- or two-digit number. Decimal points are used in the tables as placeholders for characters that should be removed from the final result. Dummy rows are put at the top of the tables to avoid having to handle a couple of cases with special-case code. SPELL3 formats a three-digit number and adds an optional suffix (e.g., thousand, million). (SPELL2 could be incorporated within SPELL3. It's separate only because it used to be called twice as a subroutine.) SPELLNUM processes each group of three digits with repeated calls to SPELL3 because this seems simpler to me than a loop or nested array statement. Reversing the digits in D makes it easier to modify SPELLNUM for a different range of allowed values. Handling zero as a special case in SPELLNUM made the lower-level code simpler. The code still needs a test added to confirm that the argument is a scalar.

{del} Z{<-}SPELLNUM N;D [1] @Spells the number {omega} in (American) English [2] @ Range checking is adjusted to the limit of IEEE 64-bit real format [3] {->}((0{<=}N)^N{<=}2*53)/L1 [4] #{<-}'The argument must be in the range [0..2*53]' [5] {->}0 @ exit without result [6] L1:Z{<-}'zero' [7] {->}(N=0)/0 @ special case for zero [8] D{<-}{reverse}(18{reshape}10){represent}N @ split digits apart [9] Z{<-}D[18 17 16]SPELL3' quadrillion' [10] Z{<-}Z,D[15 14 13]SPELL3' trillion' [11] Z{<-}Z,D[12 11 10]SPELL3' billion' [12] Z{<-}Z,D[9 8 7]SPELL3' million' [13] Z{<-}Z,D[6 5 4]SPELL3' thousand' [14] Z{<-}Z,D[3 2 1]SPELL3'' [15] Z{<-}1{drop}(Z{/=}'.')/Z @ discard padding and leading space {del} {del} Z{<-}D SPELL3 A [1] @Spells the 3 digits {alpha} and adds 'illions suffix {omega} [2] Z{<-}'' [3] {->}(D^.=0)/0 @ empty result for zero [4] {->}(D[1]=0)/L1 @ If 100 or greater, [5] Z{<-}SPELLTAB1[1+D[1];],' hundred' @ spell first digit [6] L1:Z{<-}Z,SPELL2 D[2 3] @ add tens and ones place [7] Z{<-}Z,A @ thousand, million, etc. {del} {del} Z{<-}SPELL2 D;A;B [1] @Spells the one- or two-digit number 10{basevalue}2{take}{omega} [2] {->}(D[1]{>=}2)/L1 [3] Z{<-}SPELLTAB1[1+10{basevalue}D;] @ spell a number <20 [4] {->}0 [5] L1:A{<-}SPELLTAB2[1+D[1];] @ tens place [6] B{<-}SPELLTAB1[1+D[2];] @ ones place [7] B[(('.'{/=}1{take}A)^'.'{/=}1{take}B)/1]{<-}'-' {+ +} @ hyphenate compound numbers [8] Z{<-}A,B {del} {del} SPELLTABS [1] @Defines the global variables used by SPELLNUM [2] SPELLTAB1{<-}20 10{reshape}'.......... one...... two...... three.... {+ +}four..... five..... six...... seven.... eight.... nine..... ten...... {+ +}eleven... twelve... thirteen. fourteen. fifteen.. sixteen.. seventeen {+ +}eighteen. nineteen.' [3] SPELLTAB2{<-}10 8{reshape}'................ twenty. thirty. forty.. {+ +}fifty.. sixty.. seventy eighty. ninety.' {del}

Transliteration notes: I'm back to trying `{<-}` and `{->}` for
assignment and goto. (Skirts go up, skirts go down.) On the first try,
I found "`{ne}1`" in the code (for notequal 1) and was concerned that this
might be misinterpreted as negative 1, so it's back to `{/=}`. I'm
starting to dislike `{le} {ge} {ne}` for relationals--they set a
precedence for cryptic abbreviations that I've tried to avoid in the
{keywords}. I've discovered one annoying thing about using @ for
comment--the @s in e-mail addresses either get converted to `{@}` by
APL2ASCII, or they get converted to comment symbols by ASCII2APL.

By the way, if you haven't heard, the software to perform and undo this transliteration is available via anonymous ftp on watserv1.waterloo.edu in the languages/apl/workspaces/aplascii directory. See the read.me file for more information. Workspaces are available for APL2 and APL*PLUS; others are still under construction.

Jim

Home Page