Python Forum
IndexError in Project Euler attempt
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
IndexError in Project Euler attempt
#1
Hi everyone!
I'm trying to familiarise myself with maths and CS, so I started doing these little Project Euler challenges.
This is the one I tried to code something to:

"A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.

Find the largest palindrome made from the product of two 3-digit numbers."

I get this error message when I try to run it:
"if str(a*b)[n]==str(a*b)[m]:
IndexError: string index out of range"
I realize that either n or m or both become bigger than they should when the program runs, but I'm not sure when/why that happens, since I reset both n and m if the inspected digits turn out not to be the same.

I've been stuck on this problem for days. I would greatly appreciate your help!

a=999
b=999
n=0
m=(len(str(a*b))-1)
while n!=len(str(a*b))-1:
    if str(a*b)[n]==str(a*b)[m]:
        n=n+1  
        m=m-1
    else:
        n=0
        m=(len(str(a*b))-1)
        if len(str(b))==3:
            b=b-1
        else:
            a=a-1
            b=999
    
print(a*b)
print(b)
Reply
#2
You are subtracting from a and b occasionally. But the problem requires that they are both 3 digit numbers. How do you make sure that is always the case?

12 and 13 seem suspicious to me. It looks like you require b to be 3 digits before subtraction, but not afterward.

Your basic problem seems to be that you are changing a/b and n/m backwards. You're calculating n and m based on a and b. But then you change a or b afterward and hope that the n and m you calculated previously will still be correct. Eventually you hit a case where it isn't.
Reply
#3
What a fun programming challenge. It is fun just coming up with a solution, but there are many different optimizations that can be tried adding additional challenge. I went from trying 810,000 combinations to 52,115 combinations to 6207 combinations to find the solution.

I think you should restart from scratch and the first thing you solve is to write a test that determines if a number is a palindrome. I wrote mine as a function. That way I could easily try different algorithms and measure how it affected execution time.

Once you get the palindrome test working you need to design an algorithm that tests all possible solutions and reports which combination of numbers produced the highest value palindrome. I am using a for loop. I know the range of three digit numbers so it is easy to specify the range of numbers over which I want to iterate. I don't think it makes much sense converting a number to a string just to count the number of digits. After I got a brute force solution that tests 810,000 combinations of numbers I found some optimizations that eventually reduced that to 6207. The big performance leaps came from analyzing the problem and reducing the range of number I needed to test.
Reply
#4
One approach could be to determine palindrome numbers starting from largest and test for 3-digits factors.

Observation:

- largest product of 3-digits factors is 999 * 999 = 998 001

Largest palindrome can be found by creating it from first three digits:

- 998 899 -> larger than 998 001
- 997 799 -> smaller than 998 001 -> largest palindrome number
- 996 699 -> second largest palindrome number
...
- 100 001 -> smallest 6-digit palindrome number

In Python code it can be something like this:

ceil = 998001
beginning = ceil // 1000         # first three numbers
end = int(str(beginning)[::-1])  # reversed first three numbers

while ceil < int(f'{beginning}{end}'):
    beginning -= 1

# beginning will equal 997 and max palindrome 997 799
Now we know max palindrome and can create descending 6-digit palindrome generator:

palindromes = (int(f'{i}{str(i)[::-1]}') for i in range(beginning, 99, -1))
Now we need to check for 3-digits factors of these palindromes and stop if we found first one.

If not found in range 100 001 .. 997 799 one can look in 5 digits range (100 x 100 = 10 000) using same principle to generate palindromes (just using first two numbers reversing):

five_digits = (int(f'{i}{str(i)[:2][::-1]}') for i in range(99999, 9999, -1))
EDIT: adding simple brute-force 3-digit factors check it will require 91 checks before match (using factorisation for checking probably more efficient):

def check_factors(num):
    for i in range(999, 99, -1):
        factor, reminder = divmod(num, i)
        if factor < 100:
            return False
        if factor < 1000 and reminder == 0:
            return True

for i, palindrome in enumerate(palindromes):
    if check_factors(palindrome):
        print(i, palindrome)
        break

# 91 906609 -> 993 * 913
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Calculate the Euler Number with more decimal places Pedroski55 10 4,534 Oct-31-2021, 04:45 AM
Last Post: Pedroski55
  Simple while loop only works on first attempt jsb83 2 2,025 Jun-20-2019, 08:57 PM
Last Post: jsb83
  3rd problem from project Euler Richard_SS 6 3,205 Jun-05-2019, 02:06 PM
Last Post: DeaD_EyE
  graphing euler method rondo 1 2,509 May-03-2019, 01:03 AM
Last Post: scidam
  Failed attempt to install pyserial skeeve 4 7,284 Nov-07-2017, 05:08 PM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020