Problem 17 "Number letter counts"

If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?


NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of "and" when writing out numbers is in compliance with British usage.

問 17 「数字の文字数」

1 から 5 までの数字を英単語で書けば one, two, three, four, five であり, 全部で 3 + 3 + 5 + 4 + 4 = 19 の文字が使われている.

では 1 から 1000 (one thousand) までの数字をすべて英単語で書けば, 全部で何文字になるか.

''注'': 空白文字やハイフンを数えないこと. 例えば, 342 (three hundred and forty-two) は 23 文字, 115 (one hundred and fifteen) は20文字と数える. なお, "and" を使用するのは英国の慣習.

const ZERO_TO_19: [&str; 20] = [
    "",
    "one",
    "two",
    "three",
    "four",
    "five",
    "six",
    "seven",
    "eight",
    "nine",
    "ten",
    "eleven",
    "twelve",
    "thirteen",
    "fourteen",
    "fifteen",
    "sixteen",
    "seventeen",
    "eighteen",
    "nineteen",
];

const ZERO_TO_90: [&str; 10] = [
    "", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety",
];

fn count_words(i: usize) -> u32 {
    match i {
        0..=19 => ZERO_TO_19[i].len() as u32,
        20..=99 => {
            let p1 = i % 10;
            let p2 = i / 10;
            (ZERO_TO_90[p2].len() + ZERO_TO_19[p1].len()) as u32
        }
        _ if i % 100 == 0 && i != 1000 => {
            let d = i / 100;
            (ZERO_TO_19[d].len() + "hundred".len()) as u32
        }
        101..=999 => {
            let p3 = i / 100;
            let p2p1 = i - p3 * 100;
            (ZERO_TO_19[p3].len() + "hundredand".len()) as u32 + count_words(p2p1)
        }
        1000 => ("onethousand".len()) as u32,
        _ => 0,
    }
}

fn main() {
    let mut sum = 0u32;
    for i in 1..=1000 {
        sum += count_words(i);
    }

    println!("{}", sum);
    assert_eq!(sum, 21124);
}