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; } } }