So i have a mathematical problem about prime power. A number x can be considered a prime power if x = p^k where p is a prime and k is a non-negative integer. For example, 81 is a prime power because 81 = 3^4. Now, form a sequence of numbers in the following way. Start by taking a random number.
If the number is a prime power, end the sequence.
If the number is not a prime power, minus that number with the biggest prime power that's not more than the number itself. Do it over and over again until a prime power is met, then stop.
For example, 34 is not a prime power. Hence we minus it with the highest prime power that's not more than it which is 32, hence 34-32=2. 2 is a prime power, so we stop. In this case, the length of the operation is 2 (because 34 -> 2).
Another example is 95. 95 isn't a prime power, so 95-89=6. 6 is also not a prime power, so we minus it again with the highest prime power, 6-5=1. 1 is a prime power (because 2^0 = 1), so we stop. In this case, the length of the operation is 3 (because 95 -> 6 -> 1).
Known that:
1 is the smallest initial number that can be formed with a length of
1 operation.
6 is the smallest initial number that can be formed with
a length of 2 operations.
95 is the smallest initial number that can
be formed with a length of 3 operations.
360748 is the smallest
initial number that can be formed with a length of 4 operations.
So i want to make an application using Python to find the smallest initial number that can be formed with a length of 5,6 and 7 operations.
Below is the syntax I've came up with. It is using looping to solve the problem. However, to find the smallest initial number that can be formed with a length of 4 or more operations, the program takes a very very long time to run. Is there any way i could improve my code to make the program to run much faster? I just want to focus on getting the number with 5,6 and 7 operations.
from sympy.ntheory import factorint
def pp(q): #to check whether it is a prime power
fact=factorint(q)
p=int(list(fact.keys())[0])
n=int(list(fact.values())[0])
if q!=p**n:
return False
else:
return True
a=[1,6][-1]
b=a*2
d=1
while d!=0:
c=b-a
if pp(b)==False and pp(c)==True:
for i in range(b-1,c-1,-1):
if i==c:
d=0
elif pp(i)==True:
b=i+a
break
elif pp(b)==False:
for i in range(b-1,c-1,-1):
if i==c:
b=b+a+1
elif pp(i)==True:
b=i+a
break
elif pp(b)==True:
b=b+a
b
I know it is a very long process. Thank you so much for your help.
Related
This is my factorising code which is used to find all the factors of a number but after roughly 7 digits, the program begins to slow down.
so I was wondering if there is any method of optimising this program to allow it to factorise numbers faster.
number = int(input("Input the whole number here?\n"))
factors = [1]
def factorization():
global factors
for i in range(1 , number):
factor = (number/i)
try:
factorInt = int(number/i)
if factorInt == factor:
factors.append(factorInt)
except ValueError:
pass
factorization()
print(factors)
The most effective optimization is by noting that when the number has non trivial factors, and the smallest of them is smaller than the square root of the number, and there is no need to continue looping past this square root.
Indeed, let this smallest factor be m. We have n = m.p and the other factor is such that p >= m. But if m > √n, then m.p >= n, a contradiction.
Note that this optimization only speeds-up the processing of prime numbers (for the composite ones, the search stops before √n anyway). But the density of primes and the fact that n is much larger than √n make it abolutely worth.
Another optimization is by noting that the smallest divisor must be a prime, and you can use a stored table of primes. (There are less than 51 million primes below one billion.) The speedup will be less noticeable.
Let me offer a NumPy-based solution. It seems quite efficient:
import numpy as np
def factorize(number):
n = np.arange(2, np.sqrt(number), dtype=int)
n2 = number / n
low = n[n2.astype(int) == n2]
return np.concatenate((low, number // low,))
factorize(34976237696437)
#array([ 71, 155399, 3170053, 492623066147, 225073763, 11033329])])
# 176 msec
This is the 10th problem in project euler in which we are supposed to find the sum of all the prime numbers below 2 million. I am using Sieve of Eratosthenes algorithm to find the prime numbers. Now I am facing and performance issue with the Sieve of Eratosthenes algorithm.
The performance goes down by a substantial amount if the print(i,"",sum_of_prime) is kept inside the loop. Is there anyway to see it working and keep the performance? If this is done with the conventional method it take some 13 minutes to get the result.
#Euler 10
#Problem:
#The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
#Find the sum of all the primes below two million.
#Author: Kshithij Iyer
#Date of creation: 15/1/2017
import time
#Recording start time of the program
start=time.time()
def sum_of_prime_numbers(limit):
"A function to get the sum prime numbers till the limit"
#Variable to store the sum of prime numbers
sum_of_prime=0
#Sieve of Eratosthenes algorithm
sieve=[True]*limit
for i in range(2,limit):
if sieve[i]:
sum_of_prime=sum_of_prime+i
for j in range(i*i,limit,i):
sieve[j]=False
print(i,"",sum_of_prime)
print("The sum of all the prime numbers below",limit,"is",sum_of_prime)
return
#sum_of_prime_numbers(10)
sum_of_prime_numbers(2000001)
print("Execution time of program is",time.time()-start)
#Note:
#I did give the conventioanl method a try but it didn't work well and was taking
#some 13 minutes to get the results.
#Algorithm for reference
#Input: an integer n > 1
#Let A be an array of Boolean values, indexed by integers 2 to n,
#initially all set to true.
#for i = 2, 3, 4, ..., not exceeding √n:
#if A[i] is true:
#for j = i2, i2+i, i2+2i, i2+3i, ..., not exceeding n :
#A[j] := false
#Output: all i such that A[i] is true.
So there are various improvements that could be made here:
Firstly, due to the nature of Eratosthenes' sieve, you can replace for i in range(2,limit): with for i in range(2,int(limit**0.5)+1): and the array will be calculated normally, but much faster; however, as a result, you would then have to sum the numbers later.
Also, you are not going to be able to read every individual prime and nor would you want to; instead, you only need the program to tell you milestones, such as every time the program reaches a certain number to check everything against.
Your program does not appear to take into account the fact that arrays start at 0, which should certainly cause some problems; however, this should be fairly fixable.
Finally, it occurs to me that your program appears to count 1 as prime; this should be another easy fix though.
I am actually solving the Problem 243 on Project Euler.
If you know the Problem 243:
The numbers d I am going to check the resilience for, are going to be multiplies of prime numbers, so they won't be dividable with 2 and all other primes up to d. The quickest function I can think of works like this:
def checkUnDivisibility(d, primeList):
for prime in primeList:
if d%prime == 0: return False
return True
def resilience(d, primeList):
allFractions = d-1
undivisibleFractions = 2 # 2 that are not divisible with d are 1 and d-1
for numerator in range(3, d-2, 2):
if checkUnDivisibility(numerator, primeList): undivisibleFractions += 1
elif gcd(d, numerator) == 1: undivisibleFractions += 1
print("the number of undivisible fractions is " + undivisibleFractions)
If you do not know the Problem 243:
if you write down all fractions with the numerator going from 1 to d and the denominator d, I want to know how many fractions there is, that can't be cancelled down.
For example, for d = 6:
Fractions: 1/6, 2/6, 3/6, 4/6, 5/6, 6/6. Those that can't be cancelled down are 1/6 and 5/6.
I know that when the denominator is a prime number, the number of those fractions is the same as the number of all the denominators and I know that 1/d and (d-1)/d are not going to be cancellable, and I do know how to write a function that will calculate the number of those fractions.
But the thing is, I am calculating this for some huge numbers and I want to have a quicker function. Is there any kind of trick or an algorithm for calculating the number of those with a function or a formula or something?
I would really appreciate the answer because I have been solving the problem for a few days now and still can't solve it for a really big d (around 15-30 digits).
I have a function in python to calculate the prime factors of a number:
def prime_factors(n):
i = 2
factors = []
while i * i <= n:
if n % i:
i += 1
else:
n //= i
factors.append(i)
if n > 1:
factors.append(n)
return factors
My question is, how many times will the program run to stop on input n?
I can figure it out fairly easy if you take an example such as 56, but abstractly, I cannot seem to write a "formula" for how many times the program will run before having calculated all prime factors.
More of a mathematics question than a programming question, but kinda interesting...
Let the prime factorization of n be of the form:
Where P1 is the smallest prime factor, P2 is the 2nd smallest etc, and Pk is the largest prime factor.
There are two groups of loop iterations to think about:
number of loops that occur because i is a prime factor of n
number of loops that occur because i is not a prime factor of n
Group 1
This number is easier, because it's always the same formula. It's the sum of each of the exponents of the prime factors minus 1, i.e.:
If you think about how the code acts when i is a prime factor (i.e. keeps looping while dividing n by i), the sum of the exponents should be fairly intuitive. You subtract 1 because the last append occurs outside the loop.
Group 2
The second group of loops is slightly more tricky, because the formula itself is actually dependent on whether az > 1, and also on the relative size of Pk and P(k-1) (the second smallest prime factor of n).
If ak > 1, then the last i that went through the loop had the value Pk. So the non-prime factor values of i that were evaluated are all the numbers between 2 and Pk that are not in the set P1 through to Pk. The formula for this turns out to be:
Remember k is the number of distinct prime factors of n. You subtract 1 at the end because it's between 2 and Pk, not 1 and Pk.
On the other hand, let's think about the case where ak = 1 (and ak < 1 is impossible, because ak is the exponent on the largest prime factor - it's got to be 1 or bigger). Then i never took the value of Pk, as the loop ends before that point because of the while i * i <= n: condition.
So in that case, what's the maximum value that i will take? Well it depends.
Remember that if ak = 1, then the last value that n took was Pk. If the second largest prime factor P(k-1) is bigger than the square root of Pk, then once the loop finishes with i = P(k-1), it will immediately exit the loop - so the largest i is P(k-1). On the other hand, if the square root of Pk is bigger, then the loop will continue up to that level before exiting. So the biggest i when ak = 1 is equal to max(P(k-1), Pk**0.5). The formula for the number of loops here would look like:
which simplifies to:
Notice that we take the floor of the square root of Pk, because i will only take integer values.
One formula to...
You put it all together, and it yields:
The loop executes about max(prime_factors(n)) times?
If n is prime, then the worst case is n times.
If I understand your question and since you are not using recursive calls; you are asking "how many times the while loop will execute in order to generate all prime numbers given integer n".
In your code; you are running a while loop with the condition i * i <= n. But since you are manipulating the variable i inside your method the answer is complex(refer #dnozay's answer).
If you are interested read this link which tells how complex it is. Keep read on this link to get insight on prime-counting function.
I am writing a code to find the largest prime factor of a very large number.
Problem 3 of Project Euler :
What is the largest prime factor of the number 600851475143 ?
I coded it in C...but the data type long long int is not sufficient enough to hold the value .
Now, I have rewritten the code in Python. How can I reduce the time taken for execution (as it is taking a considerable amount of time)?
def isprime(b):
x=2
while x<=b/2:
if(b%x)==0:
return 0
x+=1
return 1
def lpf(a):
x=2
i=2
while i<=a/2:
if a%i==0:
if isprime(i)==1:
if i>x:
x=i
print(x)
i+=1
print("final answer"+x)
z=600851475143
lpf(z)
There are many possible algorithmic speed ups. Some basic ones might be:
First, if you are only interested in the largest prime factor, you should check for them from the largest possible ones, not smallest. So instead of looping from 2 to a/2 try to check from a downto 2.
You could load the database of primes instead of using isprime function (there are dozens of such files in the net)
Also, only odd numbers can be primes (except for 2) so you can "jump" 2 values in each iteration
Your isprime checker could also be speededup, you do not have to look for divisiors up to b/2, it is enough to check to sqrt(b), which reduces complexity from O(n) to O(sqrt(n)) (assuming that modulo operation is constant time).
You could use the 128 int provided by GCC: http://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html . This way, you can continue to use C and avoid having to optimize Python's speed. In addition, you can always add your own custom storage type to hold numbers bigger than long long in C.
I think you're checking too many numbers (incrementing by 1 and starting at 2 in each case). If you want to check is_prime by trial division, you need to divide by fewer numbers: only odd numbers to start (better yet, only primes). You can range over odd numbers in python the following way:
for x in range(3, some_limit, 2):
if some_number % x == 0:
etc.
In addition, once you have a list of primes, you should be able to run through that list backwards (because the question asks for highest prime factor) and test if any of those primes evenly divides into the number.
Lastly, people usually go up to the square-root of a number when checking trial division because anything past the square-root is not going to provide new information. Consider 100:
1 x 100
2 x 50
5 x 20
10 x 10
20 x 5
etc.
You can find all the important divisor information by just checking up to the square root of the number. This tip is useful both for testing primes and for testing where to start looking for a potential divisor for that huge number.
First off, your two while loops only need to go up to the sqrt(n) since you will have hit anything past that earlier (you then need to check a/i for primeness as well). In addition, if you find the lowest number that divides it, and the result of the division is prime, then you have found the largest.
First, correct your isprime function:
def isprime(b):
x=2
sqrtb = sqrt(b)
while x<=sqrtb:
if(b%x)==0:
return 0
x+=1
return 1
Then, your lpf:
def lpf(a):
x=2
i=2
sqrta = sqrt(a)
while i<=sqrt(a):
if a%i==0:
b = a//i # integer
if isprime(b):
return b
if isprime(i):
x=i
print(x)
i+=1
return x