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.


In [1]:
numbers = [
    'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 
    'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']
numbers


Out[1]:
['zero',
 'one',
 'two',
 'three',
 'four',
 'five',
 'six',
 'seven',
 'eight',
 'nine',
 'ten',
 'eleven',
 'twelve',
 'thirteen',
 'fourteen',
 'fifteen',
 'sixteen',
 'seventeen',
 'eighteen',
 'nineteen']

In [2]:
tens = [None, 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']
tens


Out[2]:
[None,
 'ten',
 'twenty',
 'thirty',
 'forty',
 'fifty',
 'sixty',
 'seventy',
 'eighty',
 'ninety']

In [3]:
def foo(i):
    w = []
    if i >= 1000:
        w.append(numbers[i / 1000])
        w.append('thousand')
        i %= 1000
    if i >= 100:
        w.append(numbers[i / 100])
        w.append('hundred')
        i %= 100
        if i > 0:
            w.append('and')
    if i >= 20:
        w.append(tens[i / 10])
        i %= 10
        if i > 0:
            w[-1] += '-' + numbers[i]
    elif i > 0 or not w:
        w.append(numbers[i])
    return ' '.join(w)
        
print foo(1234)
print foo(24)
print foo(20)
print foo(29)
print foo(30)
print foo(31)
print foo(19)
print foo(18)
print foo(11)
print foo(10)
print foo(9)
print foo(2)
print foo(1)
print foo(0)
print foo(124)
print foo(220)
print foo(329)
print foo(430)
print foo(531)
print foo(619)
print foo(718)
print foo(811)
print foo(910)
print foo(809)
print foo(702)
print foo(601)
print foo(500)
print foo(1000)


one thousand two hundred and thirty-four
twenty-four
twenty
twenty-nine
thirty
thirty-one
nineteen
eighteen
eleven
ten
nine
two
one
zero
one hundred and twenty-four
two hundred and twenty
three hundred and twenty-nine
four hundred and thirty
five hundred and thirty-one
six hundred and nineteen
seven hundred and eighteen
eight hundred and eleven
nine hundred and ten
eight hundred and nine
seven hundred and two
six hundred and one
five hundred
one thousand

In [4]:
n = 1000
%timeit len(filter((lambda x: x if x != ' ' and x !='-' else ''), ''.join([foo(i) for i in range(1, n + 1)])))
len(filter((lambda x: x if x != ' ' and x !='-' else ''), ''.join([foo(i) for i in range(1, n + 1)])))


100 loops, best of 3: 11.2 ms per loop
Out[4]:
21124