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 [1]:
def number_to_words(n):
    a={1:'one',2:'two',3:'three',4:'four',5:'five',6:'six',7:'seven',8:'eight',9:'nine',10:'ten',11:'eleven',12:'twelve',13:'thirteen',
        14:'fourteen',15:'fifteen',16:'sixteen',17:'seventeen',18:'eighteen',19:'nineteen',20:'twenty',30:'thirty',40:'forty',
        50:'fifty',60:'sixty',70:'seventy',80:'eighty',90:'ninety',100:'hundred'
        }
   
    if n<=19:
        return(a[n])
        
    elif n>=21 and n<=29:
        b=str(n)                        # turn n into a string  
        return(a[20]+"-"+a[int(b[1])]) #turn n back to a integer and take the 1st digit as the index in our dictionary
        
        
    elif n>=31 and n<=39:
        b=str(n)
        return(a[30]+"-"+a[int(b[1])])
        
    
    elif n>=41 and n<=49:
        b=str(n)
        return(a[40]+"-"+a[int(b[1])])
    
    elif n>=51 and n<=59:
        b=str(n)
        return(a[50]+"-"+a[int(b[1])])
    
    elif n>=61 and n<=69:
        b=str(n)
        return(a[60]+"-"+a[int(b[1])])
    
    elif n>=71 and n<=79:    
        b=str(n)
        return(a[70]+"-"+a[int(b[1])])
    
    elif n>=81 and n<=89:
        b=str(n)
        return(a[80]+"-"+a[int(b[1])])
    
    elif n>=91 and n<=99:
        b=str(n)
        return(a[90]+"-"+a[int(b[1])])
    elif n==100:
        return'one hundred'
    elif n==200:
        return'two hundred'
    elif n==300:
        return'three hundred'
    elif n==400:
        return'four hundred'
    elif n==500:
        return'five hundred'
    elif n==600:
        return'six hundred'
    elif n==700:
        return'seven hundred'
    elif n==800:
        return'eight hundred'
    elif n==900:
        return'nine hundred'
    elif n==1000:
        return'one thousand'
    
    elif n>=101:
        b=str(n)            #if n=139, then b='139'
                      # c is the last two digits, so in this case, = '39'
        c=int(b[1:])
        
        return(a[int(b[0])]+" "+a[100]+" "+"and"+" "+number_to_words(c))
    
    else:
        return(a[n])                        # for numbers like 20,30,40,50...
        
number_to_words(149)


Out[1]:
'one hundred and forty-nine'

In [2]:
Z = list(range(1,1001))
X=[]
for i in Z:
    X.append(number_to_words(i))

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


In [3]:
Z = list(range(1,1001))
X=[]
for i in Z:
    X.append(number_to_words(i)) # LIST OF ALL THE WORDS!
    
assert number_to_words(10)=='ten'
assert number_to_words(55)=='fifty-five'
assert number_to_words(99)=='ninety-nine'
assert number_to_words(155)=='one hundred and fifty-five'
assert number_to_words(777)=='seven hundred and seventy-seven'

In [4]:
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 [5]:
def count_letters(n):
    """Count the number of letters used to write out the words for 1-n inclusive."""
    number_of_characters= ' '.join(number_to_words(x) for x in range(1,n+1))
    count=0
    for i in number_of_characters:
        if i !='-'and i !=' ':
            count+=1
    return count

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


In [6]:
count_letters(1)==3
count_letters(5)==19


Out[6]:
True

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

Finally used your count_letters function to solve the original question.


In [8]:
print(count_letters(1000))


21124

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