Euler problem number #4

前端 未结 14 1873
萌比男神i
萌比男神i 2021-01-03 11:00

Using Python, I am trying to solve problem #4 of the Project Euler problems. Can someone please tell me what I am doing incorrectly? The problem is to Find the larg

相关标签:
14条回答
  • 2021-01-03 11:35

    The question states:

    What is the largest prime factor of the number 600851475143?
    

    I solved this using C#, but the algorithm itself is language-agnostic.

    1. Create a method for determining if a number is prime or not. This can be brute-force (rather than using a much more efficient sieving algorithm) and looks like this:

    private static long IsPrime(long input)
            {
                if ((input % 2) == 0)
                {
                    return 2;
                }
                else if ((input == 1))
                {
                    return 1;
                }
                else
                {
                    long threshold = (Convert.ToInt64(Math.Sqrt(input)));
                    long tryDivide = 3;
                    while (tryDivide < threshold)
                    {
                        if ((input % tryDivide) == 0)
                        {
                            Console.WriteLine("Found a factor: " + tryDivide);
                            return tryDivide;
                        }
                        tryDivide += 2;
                    }
                    Console.WriteLine("Found a factor: " + input);
                    return -1;
                }
            }
    
    1. Once I have a function to determine primality, I can use this function to find the highest prime factor

    private static long HighestPrimeFactor(long input)
    {
        bool searching = true;
        long highestFactor = 0;
        while (searching)
        {
            long factor = IsPrime(input);
            if (factor != -1)
            {
                theFactors.Add(factor);
                input = input / factor; 
            }
            if (factor == -1)
            {
                theFactors.Add(input);
                highestFactor = theFactors.Max();
                searching = false;
            }
        }
        return highestFactor;
    }
    

    I hope this helps without giving too much away.

    0 讨论(0)
  • 2021-01-03 11:35

    Here is my solution:

    polindroms = [(x, y, x * y) for x in range(100, 999) for y in range(100, 999) if str(x * y) == str(x * y)[::-1]]
    print max(polindroms, key = lambda item : item[2])
    
    0 讨论(0)
  • 2021-01-03 11:38

    The other advice here is great. This code also works. I start with 999 because we know the largest combination possible is 999*999. Not python, but some quickly done pseudo code.

    public static int problem4()
        {       
        int biggestSoFar=0;
            for(int i = 999; i>99;i--){
                for(int j=999; j>99;j--){
                    if(isPaladrome(i*j))
                       if(i*j>biggestSoFar)
                            biggestSoFar=i*j;
                }
            }
            return biggestSoFar;    
        }
    
    0 讨论(0)
  • 2021-01-03 11:41

    Try computing x from the product of z and y rather than checking every number from 1 to a million. Think about it: if you were asked to calculate 500*240, which is more efficient - multiplying them, or counting up from 1 until you find the right answer?

    0 讨论(0)
  • 2021-01-03 11:47

    comparing string with an integer in

    x == z*y
    

    there are also logical errors

    start in reverse order range(999, 99, -1). that'll be more efficient. remove third loop and second comparison altogether.

    0 讨论(0)
  • 2021-01-03 11:48

    This adds a couple of optimizations to @GreggLind's good solution, cutting the run time in half:

    def is_palindrome(n):
        s = str(n)
        return s == s[::-1]
    
    def biggest():
        big_x, big_y, max_seen = 0,0, 0
        for x in xrange(999,99,-1):
            # Optim. 1: Nothing in any row from here on can be bigger.
            if x*x < max_seen: break  
    
            for y in xrange(x, 99,-1):  # so we don't double count   
                # Optim. 2: break, not continue
                if x*y < max_seen: break  # since we're decreasing, 
                                    # nothing else in the row can be bigger
    
                if is_palindrome(x*y):
                    big_x, big_y, max_seen = x,y, x*y
    
        return big_x,big_y,max_seen
    
    biggest()
    # (993, 913, 906609)
    

    The line

    if x*x < max_seen: break
    

    means that once we get to the point where x is less than sqrt of largest palindrome yet seen, not only do we not need to investigate any more factors on that row; we don't even need to investigate any more rows at all, since all remaining rows would start from a number less than the current value of x.

    This doesn't reduce the number of times we call is_palindrome(), but it means many fewer iterations of the outer loop. The value of x that it breaks on is 952, so we've eliminated the checking of 853 rows (albeit the "smaller" ones, thanks to the other break).

    I also noticed that

    if x*y < max_seen: continue
    

    should be

    if x*y < max_seen: break
    

    We are trying to short-circuit the whole row, not just the current iteration of the inner loop.

    When I ran this script using cProfile, the cumulative time for biggest() was about 56 msec on average, before the optimizations. The optimizations shrank it to about 23 msec. Either optimization alone would deliver most of that improvement, but the first one is slightly more helpful than the second.

    0 讨论(0)
提交回复
热议问题