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 [2]:
def number_to_words(n):
"""Given a number n between 1-1000 inclusive return a list of words for the number."""
_1={1:' ',2:"-"}
_9={1:"one",2:"two",3:"three",4:"four",5:'five',6:'six',7:'seven',8:"eight",9:'nine',0:'',11:'and'}
_100={0:'',1:'ten',2:"twenty",3:'thirty',4:'forty',5:'fifty',6:'sixty',7:'seventy',8:'eighty',9:'ninety',10:'hundred'}
_19={1:'eleven',2:'twelve',3:'thirteen',4:'fourteen',5:'fifteen',6:'sixteen',7:'seventeen',8:'eighteen',9:'nineteen'}
#above creates all the needed combinations for up to 999 and below makes 1000
str_n=str(n)
x=int(str_n[0])
if n==1000:
first,second,third='one thousand','',''
elif len(str_n)==3: # takes care of all numbers from 100-999
if int(str_n[1:3])>10 and int(str_n[1:3])<20: # writes for x11-x19
z=int(str_n[2])
first,second,third=_9[x]+_1[1]+_100[10]+_1[1]+_9[11],' ',_19[z]
elif int(str_n[2])==0 and int(str_n[1])==0: #writes for 100,200,300,...
first,second,third=_9[x]+_1[1]+_100[10],'',''
else:
y,z=int(str_n[1]),int(str_n[2])#writes for all other numbers of length 3
first,second,third=_9[x]+_1[1]+_100[10]+_1[1]+_9[11]+_1[1],_100[y],_9[z]
elif len(str_n)==2: #takes care of 10-99
if n>10 and n<20: # writes for 11-19
y=int(str_n[1])
first,second,third='','',_19[y]
else: #writes everything else
y=int(str_n[1])
first,second,third='',_100[x],_9[y]
else: #writes for 0-9
first,second,third='','',_9[x]
answer=first+second+third
return answer
Now write a set of assert tests for your number_to_words function that verifies that it is working as expected.
In [3]:
In [120]:
assert number_to_words(333)=="three hundred and thirtythree"
assert number_to_words(21)=='twentyone'
assert number_to_words(20)=='twenty'
assert number_to_words(19)=='nineteen'
assert number_to_words(219)=='two hundred and nineteen'
assert number_to_words(1)=='one'
assert number_to_words(1000)=='one thousand'
assert number_to_words(101)=='one hundred and one'
assert number_to_words(180)=='one hundred and eighty'
assert number_to_words(100)=='one hundred'
In [121]:
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 [123]:
def count_letters(n):
"""Count the number of letters used to write out the words for 1-n inclusive."""
numbers=[i for i in range(1,n+1)]
l=[number_to_words(i) for i in numbers]
f=''.join(l)
f1=f.replace(' ','')
f2=f1.replace('-','')
return len(f2)
Now write a set of assert tests for your count_letters function that verifies that it is working as expected.
In [124]:
assert count_letters(1)==3
assert count_letters(5)==19
assert count_letters(10)==39
assert count_letters(115)-count_letters(114)==20
In [125]:
assert True # use this for grading the count_letters tests.
Finally used your count_letters function to solve the original question.
In [126]:
count_letters(1000)
Out[126]:
In [127]:
assert True # use this for gradig the answer to the original question.