1

I can't wrap my head around what's causing the index error here, not exactly looking for a quick fix. Let me know however if my code repulses you/is incredibly ineffectual. The goal is to generate palindromes produced by the product of two four digit numbers.

Code:

for x in range(10000):
    for y in range(10000):
        product = str(x*y)
        lengthprod = len(str(product))
        for digit in range(lengthprod+1):
            if (product[digit]==product[lengthprod-digit]):
                print x,"x",y,"=",product

Traceback:

Traceback (most recent call last):
  File "<pyshell#31>", line 6, in <module>
    if (product[digit]==product[lengthprod-digit]):
IndexError: string index out of range
Louis93
  • 3,843
  • 8
  • 48
  • 94

4 Answers4

3

You iterate over values 0...lengthprod , but the legal subscripts for product are 0...lengthprod-1.

The last index is out of bounds. It references an element that is one byte beyond the end of the string.

Codie CodeMonkey
  • 7,669
  • 2
  • 29
  • 45
3

Converting a number to a string is generally a slow operation, since there are many possibilities in general (integers, floating point, scientific notation, maybe something exotic like fractions or imaginary numbers, not to mention things like handling leading zero or overwidth numbers or rounding to two decimal places). Thus, it is often a better approach for checking if a positive integer is a palindrome to reverse the digits numerically by repeatedly taking the input modulo 10 to extract the last digit, adding the digit to an accumulator that is multiplied by 10 at each step, then dividing the input number by 10 before looping. I don't speak Python, so here is my Scheme program to reverse a number:

(define (rev n)
  (let loop ((n n) (r 0))
    (if (zero? n) r
      (loop (quotient n 10)
            (+ (* r 10) (modulo n 10))))))

Then you can check if the number is a palindrome by checking if the input number equals its reversal.

Edit: Here it is in Python:

def rev(n):
    r = 0
    while n > 0:
        r = r * 10 + n % 10
        n = n // 10
    return r
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
user448810
  • 17,381
  • 4
  • 34
  • 59
  • cool. http://stackoverflow.com/questions/199184/how-do-i-check-if-a-number-is-a-palindrome – wim Aug 26 '11 at 00:44
2

Two changes:

1: range(0, lengthprod+1) should be range(0, lengthprod)

See documentation on range()

2: product[lengthprod-digit] should be product[lengthprod-digit-1]

Off by one error since lengthprod is a length (1 based) and digit is an index (0 based).

Note, this will only give you valid "single digit" palindromes, but gets you past the index out of range error.

David
  • 546
  • 2
  • 10
  • Wow why am I getting only single digit palindromes? EDIT: Actually, nevermind I'll think on it. Thanks for help with the bug! – Louis93 Aug 25 '11 at 03:57
1

Your code repulses me! (Sorry, I wouldn't normally be so rude, but since you asked for it... ;)

  • Use xrange rather than range for long loops like this.
  • Start the range from 1 rather than 0 unless you don't mind all the duplicated trivial results.
  • Since multiplication commutes, you might want to loop over a "triangle" rather than a "square" to avoid duplicates.
  • Your variable name product shadows a function from numeric core.
  • The question says you're interested in the "product of two four digit numbers", but your code has no such restrictions on the number of digits in the numbers. If you want the four digit numbers as input, just start your xrange(start, stop) from 1000.

Since your stated "goal is to generate palindromes", how about to try it with the correct tool for the job: generators!

def pairs(n):
  for x in xrange(n):
    for y in xrange(n):
      yield (x,y)

pairs_generator = pairs(100)

filter(None, ['{x}*{y}={xy}'.format(x=x,y=y,xy=x*y) if str(x*y) == str(x*y)[::-1] else None for x,y in pairs_generator])

I kept my generator simple for clarity's purpose. I will leave it as an exercise for you to simply make a generator to spit out the palindromes. This will involve moving the logic which I have put in my list comprehension into the generator (or you could make a new palindrome_generator which uses a pairs_generator).

Have fun!

wim
  • 338,267
  • 99
  • 616
  • 750