Project Euler Problem 17: Number Letter Counts

The source code for this problem can be found here.

Problem Statement

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.

Solution Discussion

Use the rules of English to construct the string representing the numbers from \(1\) to \(1000\), remove characters not to be counted, then calculate the total length of that string.

Solution Implementation

def number_to_english(n: int) -> str:
    """ Translate an integer into words form

    :param n: the integer to translate
    :return: the English phrasing of :math:`n`

    >>> number_to_english(127)
    'one hundred and twenty-seven'
    """

    ones = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve",
            "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
    tens = [None, None, "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]
    if 0 <= n < 20:
        return ones[n]
    elif 20 <= n <= 90 and n % 10 == 0:
        return tens[n // 10]
    elif 20 < n < 100:
        return tens[n // 10] + "-" + ones[n % 10]
    elif 100 <= n <= 900 and n % 100 == 0:
        return ones[n // 100] + " hundred"
    elif 100 < n < 1000:
        return ones[n // 100] + " hundred and " + number_to_english(n % 100)
    elif 1000 < n < 10000:
        pass
    elif n == 1000:
        return "one thousand"
    else:
        raise ValueError("unexpected input")


def solve():
    """ Compute the answer to Project Euler's problem #17 """
    target = 1000
    answer = 0
    for i in range(target):
        words = number_to_english(i + 1).replace(" ", "").replace("-", "")
        answer += len(words)
    return answer


expected_answer = 21124
solutions.problem17.number_to_english(n)

Translate an integer into words form

Parameters:n (int) – the integer to translate
Return type:str
Returns:the English phrasing of \(n\)
>>> number_to_english(127)
'one hundred and twenty-seven'
solutions.problem17.solve()

Compute the answer to Project Euler’s problem #17