-3

This Program checks how many prime integers between two ranges and their sum should also be prime. How can I reduce the running time?. HERE IS THE OPTIMIZED PRIME FUNC (eprime). BUT SILL IT EXCEEDES TIME WHICH IS 3 SEC HOW CAN I OPTIMIZE IT MORE? i really did my best but i cant find any other way.

import math
def eprime(num):
    if num < 2:
        return False
    if num % 2 == 0:
        return num == 2
    div = 3
    while div * div <= num:
        if num % div == 0:
            return False
        div += 2
    return True

x=input()
array=[]
count=0
counter=0
x=int(x)
for i in range(0,x):         # getting input from user and the ranges
    y=input().split()
    size=len(y)-1
    a=int((y[0]))
    b=int(y[size])+1

    for num in range(a,b):  # iterating on the ranges to check each number=prime?
        if eprime(num):
         num2=str(num)
         size3=len(num2)
         if(size3>=2):
          for j in range (0,size3):    # count= sum of num. if (11) then count=2
            count+=int(num2[j])
            num=count 
          if  eprime(num) and (num!=0):  # if count=prime then increment counter
            counter+=1

          count=0 
         else:
          counter+=1

    array.append(counter)
    counter=0
size2=len(array)
for i in range (0,size2):
   print(array[i])


////////////////////////////////////////////////////////////////   

Expected:

        sample input: 2
                      1 9
                      2 5
        sample output: 4
                       3
zeyad
  • 43
  • 3
  • 2
    your indent is screwed up. did you review your question? – Jason Hu Jun 15 '15 at 16:50
  • more over this program doesnt work with big number like the range between 1 - 100 – zeyad Jun 15 '15 at 16:56
  • Your program has syntax errors that precede any analysis of how the code actually runs: if the code cannot be properly run, how can we troubleshoot how it is running. – Alex Huszagh Jun 15 '15 at 17:58

1 Answers1

1

You are asking two questions which I will summarize below:

  1. What is the fastest way for a primality test. Ans: Well, its a duplicate of this question. Check Alexandru's answer.

  2. Why is your code not running for long ranges. Well check your identation. Its horrible. But look closely to this block of code.

(Near Line 33):

if  eprime(num)==True and (num!=0):
        counter+=1
        count=0

You are making the count 0 only if your number comes out to be prime. Well, this is wrong as in the next loop the count value will not be zero as it should be. This statement should be out of loop.

if  eprime(num)==True and (num!=0):
        counter+=1

    count=0

This fixes the problem.

My other thoughts:

  1. Checkout this block of code:

(Near Line 29):

for j in range (0,size3):
         count+=int(num2[j])
         num=count   <-- Value assigned to `num` 



if  eprime(num)==True and (num!=0):
        counter+=1
        count=0 

But you have already defined num to the loop variable. for num in range(a,b): Now you are again assigning value to num. Why??

Though in your case this does not causes any problem, use as many variables as you like. Assign it to some other variable numx. Because it makes your code look nice and less chance of error.

  1. You must always beautify your code and make is less lengthy before posting it to stackoverflow. This makes your question much more likable and easily answered.

Edit (How to make your primality check faster):

Your code is doing two major tasks:

  1. Dividing a number by everything that is below that. e.g. 6 is divided by 2, 3, 4, and 5.
  2. Adding the digits of numbers to check if their sum is prime or not.

The second point does not go through many loops, hence its safe to ignore that. (For now).

For the first point do the following:

  1. You know that if something is divided by 2, then its a waste to check for 4, 6, 8, and so on. So straight away avoid checking for any even number.
  2. Similarly if already the number is divisible by 3, there is no point in checking for 6, 9, and so on. The pattern in step 1 and 2 is that do not try and check the multiple of base numbers.
  3. Only check till the square root of a number in a loop. E.g. if you are checking for number 40. Then square root of 40 is roughly 7. So if any number till 7 has not divided 40, then its guaranteed that any number after 7 will definitely not divide 40. So its pointless to go more than 7.

What I suggest is for you is to try and reduce the sample space by some degree. E.g. if your range is from 1 to 100, create a list which contains all numbers 1 to 100. Then start a loop and try to cross out some numbers from them. E.g. cross out 1, multiple of 2, 3, 5, 7 and more if you like. The more you add, the better becomes your chances because then you will only waste time doing equality tests rather than looping. In the end, the list in your hand will contain only those numbers which have greater chance of being a prime number. Infact if you are planning to run this program many times, you might consider pre-compiling your result for lets say 100,000 and just using this list in each of your run.

Then also apply rule number 3. This should make your program much faster than what it is today.

Point number 4 where it all becomes very serious: Now if you still want more power, note that your function to check for primality is independent from your program. i.e. you just pass it numbers and it gives you true false. Hence you can run this function in many threads and that should increase the speed of your program.

Community
  • 1
  • 1
Rash
  • 7,677
  • 1
  • 53
  • 74
  • Thanks @rash i fixed everything but still it says time limit exceeds – zeyad Jun 15 '15 at 19:30
  • @zeyad what is your range ? – Rash Jun 15 '15 at 19:31
  • Time limit exceedes when ranges be big like 1-1000000 – zeyad Jun 15 '15 at 20:25
  • I know i should use dynamic programmnig to avoid computing old numbers like saving them in array or something but i dont knw how to implement it – zeyad Jun 15 '15 at 20:27
  • @zeyad If you are dealing with such big numbers, note where your loops are. Your main time is spent on checking for primality. Did you implement the solution that I linked (point no 1 at the top of my answer) ? – Rash Jun 15 '15 at 20:30
  • Yes i did that . But no change – zeyad Jun 15 '15 at 21:15
  • @zeyad in future if you wish to check why your program is taking too much time, you might wish to time your functions and programs so that you can analyze how much time each part of your code is taking. As per your request for dynamic programming, check my edit in my answer. This should be a fun exercise for you. I hope. :) – Rash Jun 15 '15 at 21:50
  • i optimized the function and edited it above but still i get exceeded the time limit – zeyad Jun 15 '15 at 23:54
  • @zeyad in your edit I cannot see much change. you added `while div * div <= num:` this block of code which is wrong because you are now checking the num to be divisible with 9, 15, 21 and so on. why not check with other numbers? you say that your requirement is to be < 3 sec, but dude where is your parallel code? where are you making use of pre-compiled lists, and where is my option no 3 -> only loop till the square root of a number. Plainly iterating in loop will never complete in less than 3 sec. Best of luck. :) – Rash Jun 16 '15 at 00:20