I would appreciate some feedback on the below code I wrote for a Project Euler problem. The answer comes out correct but I'd like feedback on the design of the function and implementation of docstrings. It seems to me that it may be overly complicated but I'm not sure how to simplify.
"""
Number letter counts
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.
Answer = 21124
"""
num_word_map = {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: 'thousand'}
def convert_to_word(x, spacing=''):
"""
Recursive function that converts number to it's equivalent word up to a limit of 9999.
Function is called recursively until x < 20.
Parameters
----------
x : number to convert to word
spacing : keeps track appropriate value to enter between words. This will be 'and' or an empty string
Returns
-------
Equivalent word for the number x
"""
if x / 1000 == 1:
return convert_to_word(x // 1000) + num_word_map[1000]
if 0 < x//100 < 10:
if x % 100:
return convert_to_word(x//100) + num_word_map[100] + convert_to_word(x % 100, 'and')
else:
return convert_to_word(x//100) + num_word_map[100]
elif 2 <= x//10 < 10:
return spacing + num_word_map[x - (x % 10)] + convert_to_word(x % 10)
# 0 included to prevent TypeError on a value like 80
elif 0 <= x < 20:
return spacing + num_word_map[x]
else:
"Value out of bounds"
def count_letters(limit=1000):
"""
Counts the number of letters in a word corresponding to a number from one to limit
Parameters
----------
limit : upper limit of numbers to convert and count to
Returns
-------
None
"""
count = 0
for val in range(1, limit + 1):
s = convert_to_word(val)
print(s)
count += len(s)
print(count)
if __name__ == '__main__':
count_letters()