Skip to content

Instantly share code, notes, and snippets.

@silverweed
Created March 4, 2020 10:54
Show Gist options
  • Save silverweed/7b78d1a3dcbeb75abbecbe8b52f1a1fb to your computer and use it in GitHub Desktop.
Save silverweed/7b78d1a3dcbeb75abbecbe8b52f1a1fb to your computer and use it in GitHub Desktop.
English number speller
use std::borrow::Cow;
type NumType = u128;
fn read_num_from_args() -> Result<NumType, Cow<'static, str>> {
let mut args = std::env::args();
let program_name = args.next().unwrap();
let num = if let Some(num) = args.next() {
if let Ok(num) = u128::from_str_radix(&num, 10) {
num
} else {
return Err(Cow::Borrowed("Error: argument is not a valid number."));
}
} else {
return Err(Cow::Owned(format!("Usage: {} <integer>", program_name)));
};
Ok(num)
}
const DIGITS: [&str; 10] = [
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"
];
const SPECIAL_TEN: [&str; 10] = [
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
];
const TENTHS: [&str; 8] = [
"twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety"
];
fn spell_up_to_thousand(num: NumType) -> String {
debug_assert!(num < 1000);
let mut spelled = String::new();
let hundreds = num / 100;
if hundreds > 0 {
spelled.push_str(DIGITS[hundreds as usize]);
spelled.push(' ');
spelled.push_str("hundred");
if hundreds > 1 {
spelled.push('s');
}
spelled.push(' ');
}
let num = num - hundreds * 100;
if num >= 10 && num < 20 {
spelled.push_str(SPECIAL_TEN[(num - 10) as usize]);
} else {
let tenths = num / 10;
if tenths > 0 {
debug_assert_ne!(tenths, 1);
spelled.push_str(TENTHS[(tenths - 2) as usize]);
}
let units = num - tenths * 10;
debug_assert!(units < 10, "units is {}", units);
if units > 0 {
spelled.push_str(DIGITS[units as usize]);
}
}
spelled
}
fn spell_number(num: NumType) -> String {
let mut spelled = String::new();
let billions = num / 1_000_000_000;
if billions > 0 {
spelled.push_str(&spell_number(billions));
spelled.push(' ');
spelled.push_str("billion");
if billions > 1 {
spelled.push('s');
}
spelled.push(' ');
}
let num = num - billions * 1_000_000_000;
let millions = num / 1_000_000;
if millions > 0 {
spelled.push_str(&spell_up_to_thousand(millions));
spelled.push(' ');
spelled.push_str("million");
if millions > 1 {
spelled.push('s');
}
spelled.push(' ');
}
let num = num - millions * 1_000_000;
let thousands = num / 1000;
if thousands > 0 {
spelled.push_str(&spell_up_to_thousand(thousands));
spelled.push(' ');
spelled.push_str("thousand");
if thousands > 1 {
spelled.push('s');
}
spelled.push(' ');
}
let num = num - thousands * 1000;
spelled.push_str(&spell_up_to_thousand(num));
spelled
}
fn main() {
let num = read_num_from_args();
if let Ok(num) = num {
let mut spelled = String::new();
spelled.push_str(&spell_number(num));
spelled = spelled.replace(" ", " ");
println!("{}", spelled);
} else {
let mut incr = 1;
let mut cnt = 0;
let mut i = 0;
loop {
let mut spelled = String::new();
spelled.push_str(&spell_number(i));
spelled = spelled.replace(" ", " ");
println!("{}: {}", i, spelled);
i += incr;
cnt += 1;
if cnt == 10 {
incr *= 10;
cnt = 0;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment