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 [18]:
def round_down(n):
s = str(n)
if n <= 20:
return n
elif n < 100:
return int(s[0] + '0'), int(s[1])
elif n<1000:
return int(s[0] + '00'),int(s[1]),int(s[2])
In [19]:
assert round_down(5) == 5
assert round_down(55) == (50,5)
assert round_down(222) == (200,2,2)
In [33]:
def number_to_words(n):
"""Given a number n between 1-1000 inclusive return a list of words for the number."""
lst = []
dic = {
0: 'zero',
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: 'one hundred',
200: 'two hundred',
300: 'three hundred',
400: 'four hundred',
500: 'five hundred',
600: 'six hundred',
700: 'seven hundred',
800: 'eight hundred',
900: 'nine hundred'}
for i in range(1,n+1):
if i <= 20:
for entry in dic:
if i == entry:
lst.append(dic[i])
elif i < 100:
first,second = round_down(i)
for entry in dic:
if first == entry:
if second == 0:
lst.append(dic[first])
else:
lst.append(dic[first] + '-' + dic[second])
elif i <1000:
first,second,third = round_down(i)
for entry in dic:
if first == entry:
if second == 0 and third == 0:
lst.append(dic[first])
elif second == 0:
lst.append(dic[first] + ' and ' + dic[third])
elif second == 1:
#For handling the teen case
lst.append(dic[first] + ' and ' + dic[int(str(second)+str(third))])
elif third == 0:
#Here I multiply by 10 because round_down removes the 0 for my second digit
lst.append(dic[first] + ' and ' + dic[second*10])
else:
lst.append(dic[first] + ' and ' + dic[second*10] + '-' + dic[third])
elif i == 1000:
lst.append('one thousand')
return lst
In [34]:
number_to_words(5)
Out[34]:
Now write a set of assert tests for your number_to_words function that verifies that it is working as expected.
In [35]:
assert len(number_to_words(5))==5
assert len(number_to_words(900))==900
assert number_to_words(50)[-1]=='fifty'
In [36]:
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 [37]:
def count_letters(n):
"""Count the number of letters used to write out the words for 1-n inclusive."""
lst2 = []
for entry in number_to_words(n):
count = 0
for char in entry:
if char != ' ' and char != '-':
count = count + 1
lst2.append(count)
return lst2
Now write a set of assert tests for your count_letters function that verifies that it is working as expected.
In [38]:
assert count_letters(1) == [3]
assert len(count_letters(342)) == 342
assert count_letters(5) == [3,3,5,4,4]
In [39]:
assert True # use this for grading the count_letters tests.
Finally used your count_letters function to solve the original question.
In [40]:
print(sum(count_letters(1000)))
In [29]:
assert True # use this for gradig the answer to the original question.
In [ ]: