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 [32]:
def number_to_words(n):
    """Given a number n between 1-1000 inclusive return a list of words for the number."""
    # YOUR CODE HERE
    k = []
    #Dictionaries containg modifiers for the numbers.
    j = {'0':'', '1':'one', '2':'two', '3':'three', '4':'four',
         '5':'five', '6':'six', '7':'seven', '8':'eight', '9':'nine'}
    t = {'0':'', '1':'teen', '2':'twenty', '3':'thirty', '4':'forty', '5':'fifty',
         '6':'sixty', '7':'seventy', '8':'eighty', '9':'ninety'}
    #Takes numbers from 1 to and including n, changes to string.
    for i in range(1,n+1):
        i = str(i)
    #Replaces string numbers with their worded counterpart.
        if len(i) == 1:
            k.append(j[i])
    #Special cases that don't fit pattern.
        elif len(i) == 2 and int(i) == 10:
            k.append('ten')
        elif len(i) == 2 and int(i) == 11:
            k.append('eleven')
        elif len(i) == 2 and int(i) == 12:
            k.append('twelve')
        elif len(i) == 2 and int(i) == 13:
            k.append('thirteen')
        elif len(i) == 2 and int(i) == 15:
            k.append('fifteen')
        elif len(i) == 2 and int(i) == 18:
            k.append('eighteen')
    #Case where the teens are in reversed order compared to larger numbers.
        elif len(i) == 2 and int(i)<20:
            l = i[0:1]
            v = i[1:2]
            k.append(j[v]+t[l])
        elif len(i) == 2:
            l = i[0:1]
            v = i[1:2]
            if v == '0':
                k.append(t[l])
            else:
                k.append(t[l]+'-'+j[v])
    #Same as above, but for numbers in hundreds.
        elif len(i) == 3:
            l=i[0:1]
            v=i[1:2]
            d=i[2:3]
            if v+d == '10':
                k.append(j[l]+' hundred and ten')
            elif v+d == '11':
                k.append(j[l]+' hundred and eleven')
            elif v+d == '12':
                k.append(j[l]+' hundred and twelve')
            elif v+d == '13':
                k.append(j[l]+' hundred and thirteen')
            elif v+d == '15':
                k.append(j[l]+' hundred and fifteen')
            elif v+d == '18':
                k.append(j[l]+' hundred and eighteen')
            elif len(v+d) == 2 and int(v+d)<20 and v=='0' and d=='0':
                k.append(j[l]+' hundred')
            elif len(v+d) == 2 and int(v+d)<20:
                k.append(j[l]+' hundred and '+j[d]+t[v])
            elif d == '0' and v=='0':
                k.append(j[l] + ' hundred')
            elif d == '0' and v!='0':
                k.append(j[l]+ ' hundred and '+t[v])
            else:
                k.append(j[l]+' hundred and '+t[v]+'-'+j[d])
        elif len(i) == 4 and int(i)==1000:
            k.append('one thousand')
        else:
            return False
    #Returns list with values 1 to n in words.
    return k

print(number_to_words(200))


['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', 'twenty-one', 'twenty-two', 'twenty-three', 'twenty-four', 'twenty-five', 'twenty-six', 'twenty-seven', 'twenty-eight', 'twenty-nine', 'thirty', 'thirty-one', 'thirty-two', 'thirty-three', 'thirty-four', 'thirty-five', 'thirty-six', 'thirty-seven', 'thirty-eight', 'thirty-nine', 'forty', 'forty-one', 'forty-two', 'forty-three', 'forty-four', 'forty-five', 'forty-six', 'forty-seven', 'forty-eight', 'forty-nine', 'fifty', 'fifty-one', 'fifty-two', 'fifty-three', 'fifty-four', 'fifty-five', 'fifty-six', 'fifty-seven', 'fifty-eight', 'fifty-nine', 'sixty', 'sixty-one', 'sixty-two', 'sixty-three', 'sixty-four', 'sixty-five', 'sixty-six', 'sixty-seven', 'sixty-eight', 'sixty-nine', 'seventy', 'seventy-one', 'seventy-two', 'seventy-three', 'seventy-four', 'seventy-five', 'seventy-six', 'seventy-seven', 'seventy-eight', 'seventy-nine', 'eighty', 'eighty-one', 'eighty-two', 'eighty-three', 'eighty-four', 'eighty-five', 'eighty-six', 'eighty-seven', 'eighty-eight', 'eighty-nine', 'ninety', 'ninety-one', 'ninety-two', 'ninety-three', 'ninety-four', 'ninety-five', 'ninety-six', 'ninety-seven', 'ninety-eight', 'ninety-nine', 'one hundred', 'one hundred and one', 'one hundred and two', 'one hundred and three', 'one hundred and four', 'one hundred and five', 'one hundred and six', 'one hundred and seven', 'one hundred and eight', 'one hundred and nine', 'one hundred and ten', 'one hundred and eleven', 'one hundred and twelve', 'one hundred and thirteen', 'one hundred and fourteen', 'one hundred and fifteen', 'one hundred and sixteen', 'one hundred and seventeen', 'one hundred and eighteen', 'one hundred and nineteen', 'one hundred and twenty', 'one hundred and twenty-one', 'one hundred and twenty-two', 'one hundred and twenty-three', 'one hundred and twenty-four', 'one hundred and twenty-five', 'one hundred and twenty-six', 'one hundred and twenty-seven', 'one hundred and twenty-eight', 'one hundred and twenty-nine', 'one hundred and thirty', 'one hundred and thirty-one', 'one hundred and thirty-two', 'one hundred and thirty-three', 'one hundred and thirty-four', 'one hundred and thirty-five', 'one hundred and thirty-six', 'one hundred and thirty-seven', 'one hundred and thirty-eight', 'one hundred and thirty-nine', 'one hundred and forty', 'one hundred and forty-one', 'one hundred and forty-two', 'one hundred and forty-three', 'one hundred and forty-four', 'one hundred and forty-five', 'one hundred and forty-six', 'one hundred and forty-seven', 'one hundred and forty-eight', 'one hundred and forty-nine', 'one hundred and fifty', 'one hundred and fifty-one', 'one hundred and fifty-two', 'one hundred and fifty-three', 'one hundred and fifty-four', 'one hundred and fifty-five', 'one hundred and fifty-six', 'one hundred and fifty-seven', 'one hundred and fifty-eight', 'one hundred and fifty-nine', 'one hundred and sixty', 'one hundred and sixty-one', 'one hundred and sixty-two', 'one hundred and sixty-three', 'one hundred and sixty-four', 'one hundred and sixty-five', 'one hundred and sixty-six', 'one hundred and sixty-seven', 'one hundred and sixty-eight', 'one hundred and sixty-nine', 'one hundred and seventy', 'one hundred and seventy-one', 'one hundred and seventy-two', 'one hundred and seventy-three', 'one hundred and seventy-four', 'one hundred and seventy-five', 'one hundred and seventy-six', 'one hundred and seventy-seven', 'one hundred and seventy-eight', 'one hundred and seventy-nine', 'one hundred and eighty', 'one hundred and eighty-one', 'one hundred and eighty-two', 'one hundred and eighty-three', 'one hundred and eighty-four', 'one hundred and eighty-five', 'one hundred and eighty-six', 'one hundred and eighty-seven', 'one hundred and eighty-eight', 'one hundred and eighty-nine', 'one hundred and ninety', 'one hundred and ninety-one', 'one hundred and ninety-two', 'one hundred and ninety-three', 'one hundred and ninety-four', 'one hundred and ninety-five', 'one hundred and ninety-six', 'one hundred and ninety-seven', 'one hundred and ninety-eight', 'one hundred and ninety-nine', 'two hundred']

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


In [33]:
# YOUR CODE HERE
assert number_to_words(1)[0] == 'one'
assert number_to_words(100)[99] == 'one hundred'
assert number_to_words(178)[177] == 'one hundred and seventy-eight'

In [34]:
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 [41]:
def count_letters(n):
    """Count the number of letters used to write out the words for 1-n inclusive."""
    # YOUR CODE HERE
    j=[]
    for i in number_to_words(n):
    #Takes words in list k and removes spaces and hyphens. Replace with nullspace.
        u = i.replace('-', '')
        c = u.replace(' ', '')
    #takes length of words 1 to n, append to new list, and take sum of values.
        p = len(c)
        j.append(p)
    return sum(j)

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


In [42]:
# YOUR CODE HERE
assert count_letters(1) == 3
assert count_letters(5) == 19
assert count_letters(12) == 51
assert count_letters(22) == 130

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

Finally used your count_letters function to solve the original question.


In [44]:
# YOUR CODE HERE
print(count_letters(1000))


21124

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