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 [159]:
import numpy as np

In [168]:
def number_to_words(n):
    """Given a number n between 1-1000 inclusive return a list of words for the number."""
    # YOUR CODE HERE
    #raise NotImplementedError()
    ones=['one','two','three','four','five','six','seven','eight','nine','ten']
    teens=['eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen']
    tens=['twenty','thirty','forty','fifty','sixty','seventy','eighty','ninety']
    #obivous what if statements do so not going comment everything
    if n<=10:
        x=ones[n-1]
    if 10<n<20:
        x=teens[n-11]
    if n!=10 and n<100 and n%10==0:
        x=tens[int(n/10)-2]
    if 20<n<30:
        x=tens[0]+'-'+ones[n%20-1]
    if 30<n<40:
        x=tens[1]+'-'+ones[n%30-1]
    if 40<n<50:
        x=tens[2]+'-'+ones[n%40-1]
    if 50<n<60:
        x=tens[3]+'-'+ones[n%50-1]
    if 60<n<70:
        x=tens[4]+'-'+ones[n%60-1]
    if 70<n<80:
        x=tens[5]+'-'+ones[n%70-1]
    if 80<n<90:
        x=tens[6]+'-'+ones[n%80-1]
    if 90<n<100:
        x=tens[7]+'-'+ones[n%90-1]
    if 100<=n<1000:
        a = str(n)
        b = ones[int(a[0])-1]+' hundred and'
        if n%100==0:
            x = ones[int(a[0])-1]+' hundred'
        else:
            if int(a[1::])<=10:
                x=b+' '+ones[int(a[1::])-1]
            if 10<int(a[1::])<20:
                x=b+' '+teens[int(a[1::])-11]
            if int(a[1::])!=10 and int(a[1::])<100 and int(a[1::])%10==0:
                x=b+' '+tens[int(int(a[1::])/10)-2]
            if 20<int(a[1::])<30:
                x=b+' '+tens[0]+'-'+ones[int(a[1::])%20-1]
            if 30<int(a[1::])<40:
                x=b+' '+tens[1]+'-'+ones[int(a[1::])%30-1]
            if 40<int(a[1::])<50:
                x=b+' '+tens[2]+'-'+ones[int(a[1::])%40-1]
            if 50<int(a[1::])<60:
                x=b+' '+tens[3]+'-'+ones[int(a[1::])%50-1]
            if 60<int(a[1::])<70:
                x=b+' '+tens[4]+'-'+ones[int(a[1::])%60-1]
            if 70<int(a[1::])<80:
                x=b+' '+tens[5]+'-'+ones[int(a[1::])%70-1]
            if 80<int(a[1::])<90:
                x=b+' '+tens[6]+'-'+ones[int(a[1::])%80-1]
            if 90<int(a[1::])<100:
                x=b+' '+tens[7]+'-'+ones[int(a[1::])%90-1] 
    if n==1000:
        x="one thousand"
    return str(x)
#number_to_words(999)

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


In [161]:
# YOUR CODE HERE
#raise NotImplementedError()
assert number_to_words(5) == 'five'
assert number_to_words(100) == 'one hundred'
assert number_to_words(435) == 'four hundred and thirty-five'

In [162]:
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 [163]:
def count_letters(n):
    """Count the number of letters used to write out the words for 1-n inclusive."""
    # YOUR CODE HERE
    #raise NotImplementedError()
    l = []
    lit = np.ones([len(range(n))])
    #puts all the written out numbers in a list
    for i in range(n):
        l.append(number_to_words(i+1))
    #reomoves hyphens
    y = [k.replace('-','') for k in l]
    #removes spaces
    z=[m.replace(' ','') for m in y]
    #puts the length of each word w/out spaces/hyphens in array
    for j in range(n):
        lit[j]=len(z[j])
    #returns sum of all lengths in array lit
    return sum(lit)

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


In [164]:
# YOUR CODE HERE
#raise NotImplementedError()
assert count_letters(1) == 3
assert count_letters(2) == 6
assert count_letters(5) == 19

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

Finally used your count_letters function to solve the original question.


In [166]:
# YOUR CODE HERE
#raise NotImplementedError()
count_letters(1000)


Out[166]:
21124.0

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