How to find which part of code requires optimization? - python-3.x

Given two integers m, n (1 <= m <= n) find all integers between m and n whose sum of squared divisors is itself a square. 42 is one such a number.
Code works correctly on sample inputs but it is rejected by automatic code checker and reports timeout error and asks to optimize the code...
while m < n :
list_divisors = []
temp_list = []
total = 0
for number in range (m+1) :
if m%(number+1) == 0 :
list_divisors.append(number+1)
for number in list_divisors :
total+= number*number
Codewars does not show what test cases it is failing for. It just shows Execution Timed Out (12000 ms) error. Below test cases passed during sample check.
Test.assert_equals(list_squared(1, 250), [[1, 1], [42, 2500], [246, 84100]])
Test.assert_equals(list_squared(42, 250), [[42, 2500], [246, 84100]])
Test.assert_equals(list_squared(250, 500), [[287, 84100]])

Try this based on your code. No data gets stored in a list. Total is the sum of squared of whole divisors. Then, if square-root of that total is a whole number, return the list.
import math
def list_squared(number):
total = 0
for x in range(1, number+1):
if number % x == 0:
total += x*x
bounds = math.sqrt(total)
if math.ceil(bounds) == math.floor(bounds):
return [number, total]
else:
return False
def all_numbers(start, end):
numbers = []
for x in range(start, end+1):
data = list_squared(x)
if data != False:
numbers.append(data)
return numbers
x = all_numbers(1, 10000)
print(x)
1..10000 checks takes 4.7s. I am sure it can be optimized further. Does this help you?
Even faster
Switching these two lines:
total = 0
for x in range(1, number+1):
with
total = 1 + number*number
for x in range(2, math.ceil((number+1)/2)):
will cut down your runtime to around half.
Even faster..er
def list_squared(number):
total = 0
x = 1
while x <= math.sqrt(number):
if number % x == 0:
if (number/x == x) :
total += x*x
else :
total += x*x + (number/x)*(number/x)
x += 1
bounds = math.sqrt(total)
if math.ceil(bounds) == math.floor(bounds):
return [number, total]
else:
return False
If you were to change list_squared a bit to loop through only square root of the number, you will get a runtime of half a second. The idea behind it is https://www.geeksforgeeks.org/find-divisors-natural-number-set-1/.
Let's take 42 as the number. Square root is 6.48. Let's just use 6. Start with 1. 42 is divisible by 1. 42 is also divisible by the result the division, which is 42.
Go to 2. 42 is divisible by 2. The result is 21. So, 21 is also a whole divisor. Repeat that through 6 and you've covered all divisors for 42. That cuts your runtime to sqrt(n) instead of half.

It looks like you never update the values of m or n. So if m < n is True on the first iteration of your loop, it will always be True and your while loop will be infinite. This would explain the timeout, probably because Codewars stops your code from executing if it hasn't finished after 12000ms.
To remedy this, you will have to update either m or n inside your while loop so that eventually the condition m < n evaluates to False, at which point your code will "drop through" the while loop.

Related

How to find the sum of prime numbers upto a certain range in Python?

I'm absolutely new to Python and programming in general so it'd be helpful if someone can give very beginner friendly help. I'm trying to get the sum of prime numbers upto say 50.
I used the below code but it adds additional 2 on my sum. for example sum of prime number upto 50 should be 326 but I get 328 as my output
upto = int(input("Find sum of prime numbers upto : "))
sum = 0
for num in range(2, upto + 1):
for i in range(2, num):
if (int(num % i) == 0):
break;
#If the number is prime then add it.
else:
sum += num
print("\nSum of all prime numbers upto", upto, ":", sum)
Your Code is working fine and the answer of " sum of prime numbers from 1 to 50" is 328 not 326, if you still have doubt about it you can check your result with this code below :
Explanation: Given a range [l, r], the task is to find the sum of all the prime numbers within that range.
# from math lib import sqrt method
from math import sqrt
# Function to compute the prime number
def checkPrime(numberToCheck) :
if numberToCheck == 1 :
return False
for i in range(2, int(sqrt(numberToCheck)) + 1) :
if numberToCheck % i == 0 :
return False
return True
# Function to iterate the loop
# from l to r. If the current
# number is prime, sum the value
def primeSum(l, r) :
sum = 0
for i in range(r, (l - 1), -1) :
# Check for prime
isPrime = checkPrime(i)
if (isPrime) :
# Sum the prime number
sum += i
return sum
# Driver code
if __name__ == "__main__" :
l, r = 1, 50
# Call the function with l and r
print(primeSum(l, r))
I set your range in the code above just copy and paste the code in your editor and run the code , you will see the result.
There are two parts you need to handle. One is to check if the number is a prime number or not. Second is to iterate through the range of numbers. Refer to the code below,
from math import sqrt
sum = 0
#some explanation here we are iterating from 50 all the way to 1. So you can indicate your range here. -1 is the step value which tells the difference between each iteration.
for i in range(50, 0, -1):
# Check whether it is a prime number here
bPrime = True #initialize a boolean here to be indicated by the loop below
for a in range(2, int(sqrt(i)) + 1):
if i % a == 0:
bPrime = False #definitely not a prime,break the loop and set boolean to false
break
bPrime = True #not ==0 so it is a prime, set boolean to true
if (bPrime) :
# Add up if it is a prime number
sum += i
#view the results
print(sum)
It should get you 328
Hi Sumit firstly Welcome to Stackoverflow :)
Now as per your question the sum of prime numbers upto range 50 is 328 only, not 326.
But if you want the sum of first 50 odd prime numbers then you can make minor change in your code as below which will give you 326 [which is the sum of odd prime nos till range 50]
upto = int(input("Find sum of prime numbers upto : "))
sum = 0
for num in range(3, upto+1):
for i in range(2, num):
if (int(num % i) == 0):
break;
#If the number is prime then add it.
else:
sum += num
print("\nSum of all prime numbers upto", upto, ":", sum)

Printing first combination among various combinations

So I have a question:
Given an even number (greater than 2), return two prime numbers whose sum will be equal to given number. There are several combinations possible. Print only first such pair
This is for additional reference:
*Input: The first line contains T, the number of test cases. The following T lines consist of a number each, for which we'll find two prime numbers.
Note: The number would always be an even number.
Output: For every test case print two prime numbers space separated, such that the smaller number appears first. Answer for each test case must be in a new line.
Constraints: 1 ≤ T ≤ 70
2 < N ≤ 10000
Example:
Input:
5, 74, 1024, 66, 8, 9990
Output: 3 71, 3 1021, 5 61, 3 5, 17 9973
Here is what I tried:
import math
def prime(n):
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
T = int(input("No of inputs: ")) #T is the no of test cases
input_num = []
for i in range(0,T):
input_num.append(input())
lst2= []
if T in range(1,71):
for i in input_num:
if (i in range(3,1000)) and (i % 2 == 0):
for j in range(0,i):
if prime(j) == True:
lst2.append(j)
for x in lst2:
for y in lst2:
if x + y == j:
print(x,end = ' ')
print(y)
This is only taking inputs but not returning outputs.
Also my code is currently intended for all the combinations but what I want is only the first pair and I am not able to do that
I found a more elegant solution to this problem here. Java, C, C++ etc versions of solution is also present there. I am going to give the python3 solution.
# Python 3 program to find a prime number
# pair whose sum is equal to given number
# Python 3 program to print super primes
# less than or equal to n.
# Generate all prime numbers less than n.
def SieveOfEratosthenes(n, isPrime):
# Initialize all entries of boolean
# array as True. A value in isPrime[i]
# will finally be False if i is Not a
# prime, else True bool isPrime[n+1]
isPrime[0] = isPrime[1] = False
for i in range(2, n+1):
isPrime[i] = True
p = 2
while(p*p <= n):
# If isPrime[p] is not changed,
# then it is a prime
if (isPrime[p] == True):
# Update all multiples of p
i = p*p
while(i <= n):
isPrime[i] = False
i += p
p += 1
# Prints a prime pair with given sum
def findPrimePair(n):
# Generating primes using Sieve
isPrime = [0] * (n+1)
SieveOfEratosthenes(n, isPrime)
# Traversing all numbers to find
# first pair
for i in range(0, n):
if (isPrime[i] and isPrime[n - i]):
print(i,(n - i))
return
# Driven program
n = 74
findPrimePair(n)

A code that produce a number and Check if my produced of number is primes or not

I have written a code(in python) that produces a number and checks if the number is prime or not, if it is a prime it will print it.
But my code keeps producing numbers and printing them, can you give feedback on what is wrong in my approach?
val = 10
for i in range (2, (val+1)//2):
while (val+1) % i != 0 :
print(val + 1)
val = val *10
I want to check if any number ( that is multiple of ten added by one) is considered a prime number or not.
Ok this was strangly worded but I got the gist of it, I think, first we need a function to detect prime numbers
import math
def is_prime(n):
if n == 2:
return True
if n % 2 == 0 or n <= 1:
return False
sqr = int(math.sqrt(n)) + 1
for divisor in range(3, sqr, 2):
if n % divisor == 0:
return False
return True
Then if I got your idea right you want to test if a number is prime following this function x2 = x1 *10 + 1
So that gives us this
val = 10
while val <10000:
if is_prime(val + 1) == False:
print(val+1)
break
val = val * 10
Which will not go on forever, and actually breaks at the third loop at 1000(1001).
A prime is a number x that is only dividable by x and 1. So you should start to iterate through all numbers between 2 and x-1 and look if the modulus is ever equal to zero.
val = 10
for i in range (2, val-1):
if val%i == 0:
print(i)
break
You could leave the break if you want to see all the numbers your variable is dividable.

How can you print the prime numbers from 0 to 100 in python

I am writing a small program to find all prime number from a range from 0 to whatever number the user want. How should I fix my code?
I tried to swap the loop position and the algorithm but it didn't work
g=int(input("type"))
def check_prime(g):
if(g<2):
return False
for x in range(2, g+1):
v=int(math.sqrt(x))
if(x%v==0):
return False
return True
if check_prime(g):
print(x)
I expect when the user input g they will get all the prime numbers from 0 to g and also the program will tell them how many prime numbers found
It's pretty simple, this code below will return you both the count of primes and their values.
g=int(input("type"))
def check_prime(g):
count = 0
primes = []
for number in range(g+1): #considering 'g' is inclusive
primes.append(number)
count += 1
if(number < 2 or number%2 == 0):
primes = primes[:-1]
count -= 1
continue
for x in range(3, number, 2):
if (number % x) == 0:
primes = primes[:-1]
count -= 1
break
return count, primes
print (check_prime(g))

Time limit exceeded python

Im a newbie at python and i have a task. Given a number as input, i have to print the prime that belongs in the number/position on a list of primes starting from position 1 and not 0, until the input is 'END'. For example, if the input is 1, output should be the first prime which is 2, if the input is 5, output should be the 5th prime which is 11 and so. It works fine but after 3/4-digit numbers the output has a delay until i get the Error: Time limit exceeded. How can i make it run faster? Here's the code:
def primes_function(n):
primes = []
num = 2
while len(primes) <= n:
x = num // 2
while x > 1:
if num % x == 0:
break
x -= 1
else:
primes.append(num)
num += 1
return primes[n - 1]
#main
while True:
n = input()
if n == 'END':
break
elif n > '0':
n = int(n)
value = primes_function(n)
print(value)
Sorry if i made any mistakes in the description
enter image description here
I combined this answer (1) and this answer (2) to speed up the function. The two key ideas are: When testing primality of a candidate ...
... do not divide by every number (2, 3, 4, 5, 6, ...) but only by the preceding prime numbers (2, 3, 5, ...). Every non-prime number > 2 is has to have some prime factor.
... divide only by numbers that are ≤ sqrt(candidate).
import math
def nth_prime(n):
prime_list = [2]
candidate = 3
while len(prime_list) < n:
max_factor = math.sqrt(candidate)
is_prime = True
for p in prime_list:
if p > max_factor:
break
elif candidate % p == 0:
is_prime = False
break
if is_prime:
prime_list.append(candidate)
candidate += 2
return prime_list[-1]
Benchmark of different solutions:
n=9000 n=15000 n=25000 n=75000
your solution 1m38.455s - - -
linked answer (1) 0m 2.954s 8.291s 22.482s -
linked answer (2) 0m 0.352s 0.776s 1.685s 9.567s
this answer 0m 0.120s 0.228s 0.410s 1.857s
Brij's answer 0m 0.315s 0.340s 0.317s 0.318s
For every n the programs where started from scratch.
As we can see, Brij's Sieve Of Eratosthenes takes a fairly low constant amount of time. If you want to find big prime numbers below a fixed limit then that's the best solution (here n < 78499, as the 78499-th prime number is 1 000 003 which is bigger than the sieve list).
If you also want to find a lot of smaller or medium sized prime numbers or cannot accept a fixed limit then go with this solution.
def SieveOfEratosthenes():
n = 1000000
prime = [True for i in range(n+1)]
p = 2
count = 0
while (p * p <= n):
if (prime[p] == True):
count = count + 1
for i in range(p * p, n+1, p):
prime[i] = False
p += 1
seive = []
for p in range(2, n):
if prime[p]:
seive.append(p)
return seive
def primes_function(n , seive):
return seive[n - 1]
#main
seive = SieveOfEratosthenes()
while True:
n = input()
if n == 'END':
break
elif n > '0':
n = int(n)
value = primes_function(n,seive)
print(value)
Full working : https://ide.geeksforgeeks.org/QTSGQfhFV3
I have precomputed the primes below 10^6 and made a list of primes and accessed the nth prime number by the index.

Resources