Task: Number names





Java: module NumberNames
    {
    void run()
        {
        @Inject Console console;

        Int[] tests = [0, 1, -1, 11, -17, 42, 99, 100, 101, -111, 1000, 1234, 10000, 100000,
                       123456789000, 0x123456789ABCDEF];
        for (Int test : tests)
            {
            console.print($"{test} = {toEnglish(test)}");
            }
        }

    static String[] digits = ["zero", "one", "two", "three", "four",
                              "five", "six", "seven", "eight", "nine"];
    static String[] teens  = ["ten", "eleven", "twelve", "thirteen", "fourteen",
                              "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"];
    static String[] tens   = ["zero", "ten", "twenty", "thirty", "forty",
                              "fifty", "sixty", "seventy", "eighty", "ninety"];
    static String[] ten3rd = ["?", "thousand", "million", "billion", "trillion",
                              "quadrillion", "quintillion"];

    static String toEnglish(Int n)
        {
        StringBuffer buf = new StringBuffer();
        if (n < 0)
            {
            "negative ".appendTo(buf);
            n = -n;
            }

        format3digits(n, buf);
        return buf.toString();
        }

    static void format3digits(Int n, StringBuffer buf, Int nested=0)
        {
        (Int left, Int right) = n /% 1000;
        if (left != 0)
            {
            format3digits(left, buf, nested+1);
            }

        if (right != 0 || (left == 0 && nested==0))
            {
            if (right >= 100)
                {
                (left, right) = (right /% 100);
                digits[left].appendTo(buf);
                " hundred ".appendTo(buf);
                if (right != 0)
                    {
                    format2digits(right, buf);
                    }
                }
            else
                {
                format2digits(right, buf);
                }

            if (nested > 0)
                {
                ten3rd[nested].appendTo(buf).add(' ');
                }
            }
        }

    static void format2digits(Int n, StringBuffer buf)
        {
        switch (n)
            {
            case 0..9:
                digits[n].appendTo(buf).add(' ');
                break;

            case 10..19:
                teens[n-10].appendTo(buf).add(' ');
                break;

            default:
                (Int left, Int right) = n /% 10;
                tens[left].appendTo(buf);
                if (right == 0)
                    {
                    buf.add(' ');
                    }
                else
                    {
                    buf.add('-');
                    digits[right].appendTo(buf).add(' ');
                    }
                break;
            }
        }
    }



Python: TENS = [None, None, "twenty", "thirty", "forty",
        "fifty", "sixty", "seventy", "eighty", "ninety"]
SMALL = ["zero", "one", "two", "three", "four", "five",
         "six", "seven", "eight", "nine", "ten", "eleven",
         "twelve", "thirteen", "fourteen", "fifteen",
         "sixteen", "seventeen", "eighteen", "nineteen"]
HUGE = [None, None] + [h + "illion" 
                       for h in ("m", "b", "tr", "quadr", "quint", "sext", 
                                  "sept", "oct", "non", "dec")]

def nonzero(c, n, connect=''):
    return "" if n == 0 else connect + c + spell_integer(n)

def last_and(num):
    if ',' in num:
        pre, last = num.rsplit(',', 1)
        if ' and ' not in last:
            last = ' and' + last
        num = ''.join([pre, ',', last])
    return num
    
def big(e, n):
    if e == 0:
        return spell_integer(n)
    elif e == 1:
        return spell_integer(n) + " thousand"
    else:
        return spell_integer(n) + " " + HUGE[e]

def base1000_rev(n):
    
    
    while n != 0:
        n, r = divmod(n, 1000)
        yield r
 
def spell_integer(n):
    if n < 0:
        return "minus " + spell_integer(-n)
    elif n < 20:
        return SMALL[n]
    elif n < 100:
        a, b = divmod(n, 10)
        return TENS[a] + nonzero("-", b)
    elif n < 1000:
        a, b = divmod(n, 100)
        return SMALL[a] + " hundred" + nonzero(" ", b, ' and')
    else:
        num = ", ".join([big(e, x) for e, x in
                         enumerate(base1000_rev(n)) if x][::-1])
        return last_and(num)

if __name__ == '__main__':
    
    for n in (0, -3, 5, -7, 11, -13, 17, -19, 23, -29):
        print('%+4i -> %s' % (n, spell_integer(n)))
    print('')  
    
    n = 201021002001
    while n:
        print('%-12i -> %s' % (n, spell_integer(n)))
        n //= -10
    print('%-12i -> %s' % (n, spell_integer(n)))
    print('')