RosettaCodeData/Task/Number-names/Rust/number-names.rust

72 lines
2.2 KiB
Plaintext

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