Say
1. Readme
说
提供一个 0 到 999,999,999,999 之间的数字,用英语拼出这个数字.
步骤 1
处理 0 到 99 的基本情况.
如果程序的输入是22
,那么输出应该是'twenty-two'
.
如果给出超出规定范围的数字,您的程序应该大声抱怨。
这个程序的一些好的测试用例是:
0
14
50
98
-1
100
扩展
如果您使用的是 Mac,那就是 Mac OS X 的 shell 可以用say
程序大声说出来。如果您使用的是 Linux 或 Windows,则可以使用espeak
命令使用 eSpeakNG.
第 2 步
实现将数子分成块.
像1234567890
,应该产生如 1,234,567 和 890 的列表,而更简单1000
应该只产生 1 和 0.
该程序还必须报告超出范围的值。
第 3 步
现在处理在这些块之间,插入适当的缩放词.
所以1234567890
应该输出'1 billion 234 million 567 thousand 890'
该程序还必须报告超出范围的值。上限为”兆(trillion)”处就可以.
第 4 步
把它们放在一起,除了简单的英语之外什么都没有.
12345
应该给出twelve thousand three hundred forty-five
.
该程序还必须报告超出范围的值.
扩展
(正确地)使用英语and合并数字:
14
=> “fourteen”.100
=> “one hundred”.120
=> “one hundred and twenty”.1002
=> “one thousand and two”.1323
=> “one thousand three hundred and twenty-three”.
特定的 Rust 练习笔记
与本练习的其他语言版本相比,Rust 版本略有改变。我们使用 Rust 的强类型系统来限制输入,而不是要求您返回超出范围的错误。让函数处理所有有效输入要容易得多,而不是要求,使用模块的用户处理错误。
有一个 -1 版本的测试用例,但它被注释掉了。如果您的函数正确实现,则不应编译 -1 测试用例.
在测试用例中尚未实现,将”and”添加到数字文本中.
扩展
添加转换为 u64 的最大值的功能:9,223,372,036,854,775,807.
有关输出的提示,请查看最后一个测试用例.
资源
JavaRanch CattleDrive 的变体,练习 4ahttp://www.javaranch.com/say.jsp
2. 开始你的表演
pub fn encode(n: u64) -> String { unimplemented!("Say {} in English.", n); }
3. 测试代码查看
# #![allow(unused_variables)] #fn main() { // Note: No tests created using 'and' with numbers. // Apparently Most American English does not use the 'and' with numbers, // where it is common in British English to use the 'and'. #[test] fn test_zero() { assert_eq!(encode(0), String::from("zero")); } // // If the below test is uncommented, it should not compile. // /* #[test] //#[ignore] fn test_negative() { assert_eq!(encode(-1), String::from("won't compile")); } */ #[test] //#[ignore] fn test_one() { assert_eq!(encode(1), String::from("one")); } #[test] //#[ignore] fn test_fourteen() { assert_eq!(encode(14), String::from("fourteen")); } #[test] //#[ignore] fn test_twenty() { assert_eq!(encode(20), String::from("twenty")); } #[test] //#[ignore] fn test_twenty_two() { assert_eq!(encode(22), String::from("twenty-two")); } #[test] //#[ignore] fn test_one_hundred() { assert_eq!(encode(100), String::from("one hundred")); } // note, using American style with no and #[test] //#[ignore] fn test_one_hundred_twenty() { assert_eq!(encode(120), String::from("one hundred twenty")); } #[test] //#[ignore] fn test_one_hundred_twenty_three() { assert_eq!(encode(123), String::from("one hundred twenty-three")); } #[test] //#[ignore] fn test_one_thousand() { assert_eq!(encode(1000), String::from("one thousand")); } #[test] //#[ignore] fn test_one_thousand_two_hundred_thirty_four() { assert_eq!( encode(1234), String::from("one thousand two hundred thirty-four") ); } // note, using American style with no and #[test] //#[ignore] fn test_eight_hundred_and_ten_thousand() { assert_eq!(encode(810_000), String::from("eight hundred ten thousand")); } #[test] //#[ignore] fn test_one_million() { assert_eq!(encode(1_000_000), String::from("one million")); } // note, using American style with no and #[test] //#[ignore] fn test_one_million_two() { assert_eq!(encode(1_000_002), String::from("one million two")); } #[test] //#[ignore] fn test_1002345() { assert_eq!( encode(1_002_345), String::from("one million two thousand three hundred forty-five") ); } #[test] //#[ignore] fn test_one_billion() { assert_eq!(encode(1_000_000_000), String::from("one billion")); } #[test] //#[ignore] fn test_987654321123() { assert_eq!( encode(987_654_321_123), String::from( "nine hundred eighty-seven billion \ six hundred fifty-four million \ three hundred twenty-one thousand \ one hundred twenty-three" ) ); } /* These tests are only if you implemented full parsing for u64 type. */ #[test] //#[ignore] fn test_max_i64() { assert_eq!( encode(9_223_372_036_854_775_807), String::from( "nine quintillion two hundred twenty-three \ quadrillion three hundred seventy-two trillion \ thirty-six billion eight hundred fifty-four million \ seven hundred seventy-five thousand eight hundred seven" ) ); } #[test] //#[ignore] fn test_max_u64() { assert_eq!( encode(18_446_744_073_709_551_615), String::from( "eighteen quintillion four hundred forty-six \ quadrillion seven hundred forty-four trillion \ seventy-three billion seven hundred nine million \ five hundred fifty-one thousand six hundred fifteen" ) ); } #}
4. 答案
# #![allow(unused_variables)] #fn main() { const SMALL: &'static [&'static str] = &[ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", ]; const TENS: &'static [&'static str] = &[ "ones", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety", ]; const SCALE: &'static [&'static str] = &[ "", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", ]; pub fn encode(n: u64) -> String { if n < 20 { SMALL[n as usize].to_string() } else if n < 100 { let small = n % 10; let mut out = String::from(TENS[n as usize / 10]); if small > 0 { out.push('-'); out.push_str(SMALL[small as usize]); } out } else if n < 1000 { let mut out = String::from(SMALL[n as usize / 100]); out.push_str(" hundred"); let ones = n % 100; if ones > 0 { out.push(' '); out.push_str(&encode(ones)); } out } else { let mut sets: Vec<u64> = Vec::new(); let mut val = n; while val >= 1 { sets.push(val % 1000); val /= 1000; } let mut out = String::new(); while let Some(modu) = sets.pop() { let len = sets.len(); if modu == 0 { continue; } if out.len() > 0 { out.push(' '); } out.push_str(&encode(modu)); if len > 0 { out.push(' '); out.push_str(SCALE[len]); } } out } } #}