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
   }
}

#}



填充/相关