Created
March 4, 2020 10:54
-
-
Save silverweed/7b78d1a3dcbeb75abbecbe8b52f1a1fb to your computer and use it in GitHub Desktop.
English number speller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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