Project Euler: Problem 17

https://projecteuler.net/problem=17

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.

First write a number_to_words(n) function that takes an integer n between 1 and 1000 inclusive and returns a list of words for the number as described above


In [25]:
import math as math

In [26]:
def ones_to_words(n):
    onesdict = {0: "",
               1: "one",
               2: "two",
               3: "three",
               4: "four",
               5: "five",
               6: "six",
               7: "seven",
               8: "eight",
               9: "nine",
               }
    return onesdict[n]

def teens_to_words(n):
    teendict = {10: "ten",
               11: "eleven",
               12: "twelve",
               13: "thirteen",
               14: "fourteen",
               15: "fifteen",
               16: "sixteen",
               17: "seventeen",
               18: "eighteen",
               19: "nineteen",
               }
    return teendict[n]

def tens_to_words(n):
    tensdict = {2: "twenty",
               3: "thirty",
               4: "forty",
               5: "fifty",
               6: "sixty",
               7: "seventy",
               8: "eighty",
               9: "ninety",
               }
    return tensdict[n]

def number_to_words(n):
    """Given a number n between 1-1000 inclusive return a list of words for the number."""
    cent = n // 100
    tens = int(n % 100) // 10
    ones = int(n % 10)
    
    words = ""
    
    if cent > 0:
        # hundreds
        if cent == 10:
            words += "one thousand"
        else:
            words += (ones_to_words(cent) + " hundred ")
        
        # tens and ones
        if tens == 0:
            if ones == 0:
                return words
            else:
                words += "and " + ones_to_words(ones)
        elif tens == 1:
            words += "and " + teens_to_words(10 * tens + ones)
        else:
            words += "and " + tens_to_words(tens) + "-" + ones_to_words(ones)
    else:
        # tens and ones
        if tens == 0:
            words += ones_to_words(ones)
        elif tens == 1:
            words += teens_to_words(10 * tens + ones)
        else:
            words += tens_to_words(tens) + "-" + ones_to_words(ones)
    
    return words
    #raise NotImplementedError()

Now write a set of assert tests for your number_to_words function that verifies that it is working as expected.


In [27]:
assert number_to_words(4) == "four"
assert number_to_words(58) == "fifty-eight"
assert number_to_words(409) == "four hundred and nine"
assert number_to_words(1000) == "one thousand"
assert number_to_words(712) == "seven hundred and twelve"
#raise NotImplementedError()

In [28]:
assert True # use this for grading the number_to_words tests.

Now define a count_letters(n) that returns the number of letters used to write out the words for all of the the numbers 1 to n inclusive.


In [29]:
def count_letters(n):
    """Count the number of letters used to write out the words for 1-n inclusive."""
    x = number_to_words(n)
    x = x.replace("-", " ")
    return sum([len(y) for y in x.split(" ")])
    #raise NotImplementedError()

Now write a set of assert tests for your count_letters function that verifies that it is working as expected.


In [30]:
assert count_letters(4) == 4
assert count_letters(58) == 10
assert count_letters(409) == 18
assert count_letters(1000) == 11
assert count_letters(712) == 21
#raise NotImplementedError()

In [31]:
assert True # use this for grading the count_letters tests.

Finally used your count_letters function to solve the original question.


In [32]:
total_letters = 0
for i in range(1, 1001):
    total_letters += count_letters(i)
    
print(total_letters)
    
#raise NotImplementedError()


21124

In [33]:
assert True # use this for gradig the answer to the original question.