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]:
import numpy as np
In [2]:
numbers = {0: "", 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",
1000:"onethousand"}
#I did this part with two functions to make my method more straightforward
# The first function takes a number and breaks it into 1000s, 100s, 10s and 1s.
# It also adjusts for perculiar numbers such as 'eleven and 'thirteen'. The second function
# takes the number list from the first function and turns it into words.
def number_in_parts(n):
#this breaks up a number into parts
#an entry of 526 would return a list of [500, 20, 6]
broken_number = []
length = len(str(n))
for i in range(length):
f = int(str(n)[i]) * 10**(length-(i+1))
broken_number.append(f)
for i in range(len(broken_number)):
if broken_number[i] == 10:
broken_number[i]= broken_number[i] + broken_number[i+1]
broken_number[i+1] = 0
return(broken_number)
def number_to_words(entry):
"""Given a number n between 1-1000 inclusive return a list of words for the number."""
letters = []
for number in entry:
# if 100-900, adding "1-9" and "hundred"
if number >= 100 and number < 1000:
n = number/100
letters.append(numbers[n])
letters.append(numbers[100])
else:
letters.append(numbers[number])
# adding an "and" for anything above 99 with nonzero terms in the 10s or 1s place
if (letters[-1] != "" or letters[-2] != "") and len(entry) > 2:
letters.append("and")
final = "".join(letters)
return(final)
Now write a set of assert tests for your number_to_words function that verifies that it is working as expected.
In [3]:
assert number_in_parts(123) == [100, 20, 3]
assert number_in_parts(112) == [100, 12, 0]
assert number_in_parts(1000) == [1000, 0, 0, 0]
assert number_to_words(number_in_parts(100)) == "onehundred"
assert number_to_words(number_in_parts(112)) == "onehundredtwelveand"
assert number_to_words(number_in_parts(589)) == "fivehundredeightynineand"
assert number_to_words(number_in_parts(102)) == "onehundredtwoand"
assert number_to_words(number_in_parts(140)) == "onehundredfortyand"
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."""
x = 0
for i in range(n):
x += len(number_to_words(number_in_parts(i+1)))
return x
Now write a set of assert tests for your count_letters function that verifies that it is working as expected.
In [6]:
assert count_letters(1) == 3
assert count_letters(2) == 6
assert count_letters(3) == 11
assert count_letters(500) - count_letters(499) == len("fivehundred")
assert count_letters(459) - count_letters(458) == len(number_to_words(number_in_parts(459))) == len("fourhundredandfiftynine")
assert count_letters(1000) - count_letters(999) == len("onethousand")
assert count_letters(412) - count_letters(411) == len("fourhundredandtwelve")
assert count_letters(330) - count_letters(328) == len("threehundredandthirtythreehundredandtwentynine")
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))
In [ ]:
assert True # use this for gradig the answer to the original question.