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.


use std::io::{self, Write, stdout};
 
const SMALL: &[&str] = &[
    "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
    "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
    "nineteen",
];
 
const TENS: &[&str] = &[
    "PANIC", "PANIC", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety",
];
 
const MAGNITUDE: &[&str] = &[
    "PANIC", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion",
];
 
fn wordify<W: Write>(w: &mut W, mut number: i64) -> Result<(), io::Error> {
    if number == 0 {
        return write!(w, "zero");
    }
    if number < 0 {
        write!(w, "negative ")?;
        number = -number;
    }
    while number != 0 {
        if number < 20 {
            write!(w, "{}", SMALL[number as usize])?;
            break;
        } else if number < 100 {
            write!(w, "{}", TENS[number as usize / 10])?;
            number %= 10;
            if number != 0 {
                write!(w, "-")?;
            }
        } else if number < 1_000 {
            write!(w, "{} hundred", SMALL[number as usize / 100])?;
            number %= 100;
            if number != 0 {
                write!(w, " and ")?;
            }
        } else {
            let mut top = number;
            let mut magnitude = 0i64;
            let mut magnitude_pow = 1i64;
            while top >= 1_000 {
                top /= 1_000;
                magnitude += 1;
                magnitude_pow *= 1_000;
            }
            wordify(w, top)?;
            number %= magnitude_pow;
            if number == 0 {
                write!(w, " {}", MAGNITUDE[magnitude as usize])?;
            } else if number > 100 {
                write!(w, " {}, ", MAGNITUDE[magnitude as usize])?;
            } else {
                write!(w, " {} and ", MAGNITUDE[magnitude as usize])?;
            }
        }
    }
    Ok(())
}
 
fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    for &n in &[12, 1048576, 9_000_000_000_000_000_000, -2, 0, 5_000_000_000_000_000_001, -555_555_555_555] {
        wordify(&mut stdout, n).unwrap();
        write!(&mut stdout, "\n").unwrap();
    }
}