Task

Show how to spell out a number in English.

You can use a preexisting implementation or roll your own, but you should support inputs up to at least one million (or the maximum value of your language's default bounded integer type, if that's less).

Support for inputs other than positive integers (like zero, negative integers, and floating-point numbers) is optional.



Related task

   Spelling of ordinal numbers.


import <Utilities/Math.sl>;
import <Utilities/Sequence.sl>;
import <Utilities/Conversion.sl>;
import <Utilities/String.sl>;
 
main(argv(2)) := delimit(numberToEnglish(stringToInt(argv)), '\n');
 
ones := ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];
teens := ["eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"];
tens := ["ten", "twenty", "thrity", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"];
 
magnitudes := ["", "thousand", "million", "billion", "trillion"];
 
numberToEnglish(num(0)) :=
    let
        triplets[i] := 
                (num / integerPower(1000, i - 1)) mod 1000 
                foreach i within 1 ... ceiling(log(1000, num + 1));
 
        englishtTriplets[j] := numberToEnglishHelper(triplets[j]);
 
        partials[j] := 
                englishtTriplets[j] ++ magnitudes[j] ++ ", " when size(englishtTriplets[j]) > 0 
                foreach j within reverse(1 ... size(triplets));
    in
            "zero" when num = 0
        else
            "negative " ++ numberToEnglish(-num) when num < 0
        else
            trim(allButLast(trim(join(partials))));
 
 
numberToEnglishHelper(num(0)) :=
    let
        onesPlace := num mod 10;
        tensPlace := (num mod 100) / 10;
        hundredsPlace :=  (num mod 1000) / 100;
 
        onesWord :=     "ten " when tensPlace = 1 and onesPlace = 0
                    else
                        "" when onesPlace = 0
                    else
                        teens[onesPlace] ++ " " when tensPlace = 1
                    else 
                        ones[onesPlace] ++ " ";
 
        tensWord :=    "" when tensPlace = 0 or tensPlace = 1
                    else 
                        tens[tensPlace] ++ " " when onesPlace = 0
                    else 
                        tens[tensPlace] ++ "-";
 
        hundredsWord :=     "" when hundredsPlace = 0
                         else
                             ones[hundredsPlace] ++ " hundred ";
 
        andWord := "" when hundredsPlace = 0 or (tensPlace = 0 and onesPlace = 0) else "and ";
 
 
    in
        hundredsWord ++ andWord ++ tensWord ++ onesWord;