1

I'm working on Project Euler #17 and am getting an index out of range error.

Here is the text of the problem:

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.

I wanted to create a list using a loop that stores numbers from 1 to 1000 as integers, then use a function that can take the number as an argument, convert it to a string that says the number in English, and then count the number of words in each one and return that as an integer.

I then create a for loop that intakes the integers from the list and puts each one through the function.

Here is my code:

letter_count = []

#Function that intakes integer and returns number of words it has in english.
def numToWords(num):
    #Store strings that contain the names of the numbers.
    #The 0th place item is plank so that the numbers start at 1.
    units = ['', 'one', 'two',   'three','four','five','six','seven','eight','nine']
    teens = ['','eleven','twelve','thirteen','fourteen','fifteen','sixteen,'     'seventeen','eighteen','nineteen']
    tens =    ['','ten','twenty','thirty','forty','fifty','sixty','seventy','eighty','ninety']
    thousands = ['', 'thousand']

    words = []
    if num==0: words.append('zero') #Special case for when the number is 0.
    else:
        numStr = '%d'%num  #Stores number as string
        numStrLen = len(numStr)  #Checks length of string using decimal value
        groups = (numStrLen+2)/3 
        numStr = numStr.zfill(groups*3)
        for i in range(0, groups*3, 3):
            h,t,u = int(numStr[i]), int(numStr[i+1]), int(numStr[i+2])
            g = groups - (i/3+1)
            if h>=1:
                words.append(units[h])
                words.append('hundred')
                if num > 101 and num < 110:
                    words.append('and') #Adds the 'and' for numbers 101-109.
            if t>1:
                words.append(tens[t])
                if u>=1: words.append(units[u])
            elif t==1:
                if u>=1: words.append(teens[u])
                else: words.append(tens[t])
            else:
                if u>=1: words.append(units[u])
            if (g>=1) and ((h+t+u)>0): words.append(thousands[g]+',')
    return len(words)

#Loop to take integers in 1 to 1000 as arguments in the function 
#and append them to a new list
for i in range(1,1001,1):
    letter_count.append(numToWords(i))

#Print the sum of the new list to get the total number of words.
print(sum(letter_count))

When I run the code (using El Cap's python bash command) I get the following error message:

Traceback (most recent call last): File "euler017.py", line 40, in letter_count.append(numToWords(i)) File "euler017.py", line 31, in numToWords if u>=1: words.append(teens[u]) IndexError: list index out of range

I tested the function on a bunch of random numbers individually and it worked. I also tested it on a loop of numbers from 1 to 10. It's when the loop is 100 or higher that I get the error.

For the function I modified one I saw in an old post: https://stackoverflow.com/a/19193721/5960074

I am not sure how this is the case. I'm not modifying any lists but creating a new one so how can something be out of range?

Thanks for any help.

Community
  • 1
  • 1

1 Answers1

3

Move the comma between 16 and 17 out of the quotes:

you have

'sixteen,'     'seventeen'

but you want

'sixteen', 'seventeen'

Your error is not noticed by the interpreter because it's valid python:

String literal concatenation

Jasper
  • 3,939
  • 1
  • 18
  • 35
Steve
  • 1,250
  • 11
  • 25