How do you find the first m twin primes? - python

My program is supposed to find the first m twin primes and print that they are.
def isItPrime(n):
tests = primes.copy()
while len(tests) != 0:
if n % tests[-1] == 0:
return False
elif n % tests[-1] != 0:
tests.pop()
if len(tests) == 0:
primes.append(n)
return True
def findTwinPrimes(a , b):
if isItPrime(a) == True:
if isItPrime(b) == True:
if b - a == 2:
print(a, "-", b, "is a twin prime")
def firstMTwinPrimes(m):
o = 0
i = 1
if o < m :
print(i)
k = 3
l = 5
findTwinPrimes(k,l)
k += 1
l += 1
o += 1
firstMTwinPrimes(7)
Currently, it runs without errors but also does not work. The i is to check how many times the program runs and it only runs once. I do not know why becuase if o is less than m it should run again. Also for 3 and 5, they are twin primes but it doesn't work for them. isItPrime is already implemented to check if a number is prime or not. It returns the answer.

please, post your code with function and error
otherwise, try this:
def printTwinPrime(n):
prime = [True for i in range(n + 2)]
p = 2
while (p * p <= n + 1):
# If prime[p] is not changed,
# then it is a prime
if (prime[p] == True):
# Update all multiples of p
for i in range(p * 2, n + 2, p):
prime[i] = False
p += 1
# check twin prime numbers
# display the twin prime numbers
for p in range(2, n-1):
if prime[p] and prime[p + 2]:
print("(",p,",", (p + 2), ")" ,end='')
# driver program
if __name__=='__main__':
# static input
n = 7
# Calling the function
printTwinPrime(n)

As #JayMody notes, your isItPrime() is broken. We can make it work as intended, but the way it relies on being called with increasing arguments, and its use of a global primes list, are problems. (I.e. consider first calling isItPrime(22) followed by isItPrime(6))
#JohanC's answer, which you accepted, doesn't maintain a global prime list, instead doing more divisions than necessary by testing all numbers from 2 to the number. This is far less efficient than what you were attempting to implement. I think we can salvage your original intent, and not expose a non-general isItPrime() test, by making one function internal to the other:
def firstMTwinPrimes(m):
primes = [2]
def isItPrime(n):
for prime in primes:
if prime * prime > n:
break
if n % prime == 0:
return False
primes.append(n)
return True
number = 3
count = 0
while count < m:
for n in range(number, number + 3, 2):
if n == primes[-1]:
continue
if not isItPrime(n):
break
else: # no break
print(number, "-", number + 2, "are twin primes")
count += 1
number += 2
We have to be careful not to add a prime to the list twice when it's tested as a lower and upper number. You'll find this approach is a couple of orders of magnitude faster than #JohanC's answer when M exceeds a hundred. You were on the right track.
The sieve-based solution #AlokMishra posted is faster still, but it is designed to find all pairs up to some number, not some number of pairs as you specified.

Some remarks:
You need to change your if o < m to a while loop: while o < m. With only the if-test, findTwinPrimes is only called once. You need to call it again and again until you have enough twin primes. Inside that while-loop, you need to increment o only when you really found twin primes. Therefore, findTwinPrimes should return True when it found a twin prime, and False when it didn't. Also, k=3; l=5 should be put before the start of the while-loop, so they can be incremented inside the loop.
Instead of if isItPrime(a) == True: it is better to just write if isItPrime(a):. That has the same effect and is more readable.
You have a variable i that you just give a value of 1 and print, but don't do anything useful with. You can leave it out.
Python code is more readable if you indent with four spaces instead of only 2
Here is the adapted code:
def isItPrime(p):
for i in range(2, p):
if p % i == 0:
return False
return True
def findTwinPrimes(a, b):
if isItPrime(a):
if isItPrime(b):
if b - a == 2:
print(a, "-", b, "is a twin prime")
return True
return False
def firstMTwinPrimes(m):
o = 0
k = 3
l = 5
while o < m:
if findTwinPrimes(k, l):
o += 1
k += 1
l += 1
firstMTwinPrimes(7)
Output:
3 - 5 is a twin prime
5 - 7 is a twin prime
11 - 13 is a twin prime
17 - 19 is a twin prime
29 - 31 is a twin prime
41 - 43 is a twin prime
59 - 61 is a twin prime
PS: If you want, you can write
if isItPrime(a):
if isItPrime(b):
if b - a == 2:
as
if isItPrime(a) and isItPrime(b) and b - a == 2:

Related

How to write a python program that finds the first n numbers that are not divisible by any other prime number except 2, 3, and 5

I need to create a program that takes user input n and the finds the first n numbers that aren't divisible by any other prime numbers except 2, 3, and 5. This is what I've got so far:
def is_divisible(i):
for k in range(7, i):
if is_prime(k) == 1 and i % k == 0:
return 1
else:
return 0
def is_prime(k):
for j in range(2, k):
if k % j == 0:
return 0
else:
return 1
while True:
while True:
while True:
try:
n = input("How many numbers do you want to find: ")
n = n.replace(" ", "")
n = int(n)
break
except:
print("Input only natural numbers")
continue
if n == 0:
print("Input only natural numbers")
continue
else:
break
count = 0
i = 0
while count < n:
if i % 2 == 0 and i % 3 == 0 and i % 5 == 0 and is_divisible(i) == 0:
print(i)
count += 1
i += 1
else:
i += 1
repeat = input("To repeat press (1), to end press anything else: ")
if str(repeat) == "1":
continue
else:
print("Bye!")
break
If asked to find 10 numbers the program outputs:
30
60
90
120
150
180
240
270
300
330
The program didn't print 210 (which is divisible by 7) so the algorithm seems, at least, partly correct, but 330 is printed (which is divisible by 11) and I can't figure out why. If I manually change i to 330 and k to 11, the is_prime function correctly finds that 11 is a prime number, but the is_divisible function still returns 0. I can't figure out what's wrong. Any help will be greatly appreciated!
Thanks!
First, you need to fix your is_prime like #Barmar mentions above
Note, this can be optimized in multiple ways, the simplest of which is to only check for j in range(2, int(math.sqrt(k))+1) because a number k won't have any prime factors greater than sqrt(k). Also, we can memorize all the prime numbers found so far, so that if the same number is checked multiple times, subsequent checks are much faster. You can use better algorithms to check if a number is prime, but this should suffice for our purposes.
import math
# A set to remember prime numbers
primes = set()
def is_prime(k):
if k == 1: return False # 1 is not prime
if k in primes: return True # Check remembered prime numbers
# Check all numbers in the closed interval [2, sqrt(k)]
for j in range(2, int(math.sqrt(k))+1):
if k % j == 0:
return False
# Prime number, so remember it
primes.add(k)
return True
The first n numbers that aren't divisible by any prime numbers other than 2, 3, and 5
Since your number needs to be divisible by 2, 3, and 5, you don't need to look at all numbers as you do currently. Just look at multiples of 2 * 3 * 5, i.e. multiples of 30, since those are the only numbers that are going to be multiples of 2, 3, and 5.
So now your problem becomes: "Print 30 * i, where i is not a multiple of a prime number other than 2, 3, and 5. i.e., you need to get the prime factors of i, and check that this set contains only 2, 3, and 5.
There are a number of ways to get the prime factors of a number. Here's a simple one:
def prime_factors(k):
# If k is prime, it is its only prime factor
if is_prime(k):
return {k}
factors = set()
# If divisible by 2, add 2 as a prime factor
if k % 2 == 0:
factors.add(2)
# Check all odd numbers in the closed interval [3, k//2]
for i in range(3, k//2+1, 2):
if k % i == 0 and is_prime(i):
factors.add(i)
return factors
Now that we've defined our helper functions, we just need to call them:
n = 10
i = 1
count = 0
while count < n:
factors = prime_factors(i)
# If we remove {2, 3, 5} from factors, do we get an empty set?
if not factors.difference({2, 3, 5}):
print(2 * 3 * 5 * i)
count += 1
i += 1
Which prints:
30
60
90
120
150
180
240
270
300
360
If you are indeed looking for regular numbers as #Mark and #Kelly suggest in their comments, then you simply skip the multiplication by 2 * 3 * 5:
n = 10
i = 1
count = 0
while count < n:
factors = prime_factors(i)
# If we remove {2, 3, 5} from factors, do we get an empty set?
if not factors.difference({2, 3, 5}):
print(i)
count += 1
i += 1
gives:
1
2
3
4
5
6
8
9
10
12
Here's a bit of code that looks for values that have other factors besides 2,3,5. If there are other factors in there, they must be other prime values because we remove the prime factors 2,3,5 from the number.
primes = [ 2, 3, 5]
count = 10
answers = []
value = 2
while len(answers) < count:
test_value = value
for prime in primes:
while test_value % prime == 0:
test_value //= prime
if test_value == 1:
answers.append(value)
value += 1
print(answers)
Ok, the performance discussion from #Kelly Bundy bothered me - so I added a different approach - but it's got problems.
import sys
primes = [ 2, 3, 5]
count = int(sys.argv[1])
base = round( count ** (1./3.) )
powers = [0] * len(primes)
answers = []
while True:
value = 1
for n in range(len(primes)):
value *= primes[n] ** powers[n]
answers.append(value)
for n in range(len(powers)):
powers[n] += 1
if powers[n] != base:
break
powers[n] = 0
else:
break
for x in sorted(answers):
print(x)
Basically, all of the numbers we want to find are of the form: 2**x * 3**y * 5**z . And so, if we just vary x,y,and z, we can compute all of the qualifying numbers.
The the problem boils down to, which values of x,y, and z are valid. To be honest, I haven't figured that out. All I do is come up with count combinations of x,y,z where I just count values (using some base counting system). For instance, if I need to come up with 1,000 combinations, I just produce all of the combinations of x,y,z where the values are between 0 and 9. And so i get the values (000 - 999). And this produces the values: 2**0 * 3**0 * 5**0 all the way up to 2**9 * 3**9 * 5**9. Now, I'm definitely missing some values. The 1,000 numbers I come up with are NOT the first 1,000 numbers.
Your is_divisible method basically only checks 7 and then returns either 1 or 0.
You want to check all the numbers in the range.
def is_divisible(i):
for k in range(7, i):
if is_prime(k) == 1 and i % k == 0:
return 1
return 0
Your is_prime method suffers from this issue as well:
def is_prime(k):
for j in range(2, k):
if k % j == 0:
return 0
return 1
Fixing these issues, however, is going make this algorithm EXTREMELY slow so you will need to consider some strategies that will make it faster.
Caching the numbers that you have already checked for primeness would be a start.

Strange output when trying to find prime numbers Python

Ok, so I admittedly am kind of a noob, and I've been going through a course on udemy for programming. The problem is asking to write a function that finds all the prime numbers up to the number given. So I started writing the following code to extract the numbers that are not even, as well as the numbers not evenly divisible by 3 just to start:
def count_primes(num):
num_list5 = []
for i in range(num + 1):
print(i)
if i % 2 != 0 or i % 3 != 0:
num_list5.append(i)
return num_list5
When I call the function with a number of 100 like:
count_primes(100)
In the output, I get the num_list5 showing all the numbers in the range except for 6 and multiples of 6:
[1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14 ...]
Its like the if statement is doing an AND operation here... because 6 would be divisible by 2 AND 3. Is this a bug or something? Or am I not understanding and/or operations correctly?
What's weird is that it was working at one point and after making a change and reverting it, it started doing this...
I'm using VSCode and Jupyter notebooks and tried both Python 3.8.5 64-bit and 3.9.4 64-bit on Ubuntu 20.04
i % 2 != 0 or i % 3 != 0 is equal to not (i % 2 == 0 and i % 3 == 0) (De Morgan's laws)
It should be i % 2 != 0 and i % 3 != 0
If you are looking to generate all primes less than num, you should loop over all numbers j less than i and check if i%j is zero rather than just 2 and 3.
def count_primes(num):
num_list5 = []
for i in range(2, num + 1): # start at 2 because 1 and zero are not primes
print(i)
for j in range(2, i):
if i%j == 0:
break
else:
num_list5.append(i)
return num_list5
if __name__ == "__main__":
n = 100
print(count_primes(n))
Note that using Sieve of Eratosthenes method, this can be done more efficiently:
import math
def count_primes_sieve(num):
num_list5 = [False, False] + [True]*(num - 1)
for i in range(2, math.ceil(math.sqrt(num)) + 1):
if num_list5[i]:
j = i * i
while j < len(num_list5):
num_list5[j] = False
j += i
return [i for i, p in enumerate(num_list5) if p]
if __name__ == "__main__":
n = 100
print(count_primes_sieve(n))
We know some facts about prime numbers which you can use in your program. Negative numbers, 0 and 1 are not prime. 2 is the only even prime. A prime number only has itself and 1 as factors. From multiplication we know that if a x b = c then one of a, b is <= sqrt(c). That last fact helps us cut down the number of trial divisors we have to test. We can test for a prime by looking for a number that divides the target but is not the target itself or 1. If we find such a number then the target is not prime.
Here is some pseudocode to help:
function isPrime(num)
// 1, 0, negatives not prime.
if (num < 2)
return false
end if
// 2 is the only even prime.
if (num MOD 2 = 0)
return (num = 2)
end if
// Try odd factors up to square root.
limit <- 1 + sqrt(num)
for (test <- 3; test < limit; test <- test + 2)
if (num MOD test = 0)
// Not prime, we have found a factor.
return false
end if
end for
// If we get this far then num is prime.
return true
end function
After figuring out the propositional math and de Morgan's Law as someone pointed out, I was able to come up with a pretty simple solution using or and mod operators and only goes through a the sequence once:
def count_primes(num):
num_list5 = []
for i in range(2, num + 1):
if i == 2 or i == 3 or i == 5 or i == 7:
num_list5.append(i)
if not (i % 2 == 0 or i % 3 == 0 or i % 5 == 0 or i % 7 == 0):
num_list5.append(i)
return num_list5
print(count_primes(100))

Returns the smallest prime number that is a divisor of x

The following code contains a mistake that can trigger an infinite loop, I can not figure out how to get the second print statement to run, I am sure it is something simple to fix it, but just can't see it.
def smallest_prime_factor(x):
"""Returns the smallest prime number that is a divisor of x"""
# Start checking with 2, then move up one by one
n = 2
while n <= x:
if x % n == 0:
x += 1
return n
print(smallest_prime_factor(12)) # should be 2
print(smallest_prime_factor(15)) # should be 3
Instead of increasing value for x which is the number for which you are trying to find the smallest prime number factor, you need to increase n that is the factor. Also, if n divides x, then you need to return n else you need to increment the value of n outside the if block.
Try this code:
def smallest_prime_factor(x):
"""Returns the smallest prime number that is a divisor of x"""
# Start checking with 2, then move up one by one
n = 2
while n <= x:
if x % n == 0:
return n
n += 1
Also to optimize it more, you just need to run while loop till the square root of a number to find it's prime number factor, else the number itself is the prime factor.
So this is the optimized version of the above code:
def smallest_prime_factor(x):
"""Returns the smallest prime number that is a divisor of x"""
# Start checking with 2, then move up one by one
n = 2
while n*n <= x:
if x % n == 0:
return n
n += 1
return x
you get in an infinite loop because you do not change the value of n if the return condition it is not met, as you can see the return condition is met only if your number x is a multiple of 2, you have to change :
if x % n == 0:
x += 1
with:
while n <= x:
if x % n == 0:
return x
n += 1
to optimize your code you can search for a number prime n to divide x that is less than int(math.sqrt(x) + 1):
import math
def smallest_prime_factor(x):
"""Returns the smallest prime number that is a divisor of x"""
# Start checking with 2, then move up one by one
n = 2
max_n = int(math.sqrt(x) + 1)
while n < max_n:
if x % n == 0:
return n
n += 1
return x
even better you could use the Sieve of Eratosthenes to generate fast the prime numbers and test against your x:
# Sieve of Eratosthenes
# Code by David Eppstein, UC Irvine, 28 Feb 2002
# http://code.activestate.com/recipes/117119/
def gen_primes(y):
""" Generate an infinite sequence of prime numbers.
"""
# Maps composites to primes witnessing their compositeness.
# This is memory efficient, as the sieve is not "run forward"
# indefinitely, but only as long as required by the current
# number being tested.
#
D = {}
# The running integer that's checked for primeness
q = 2
while q < y:
if q not in D:
# q is a new prime.
# Yield it and mark its first multiple that isn't
# already marked in previous iterations
#
yield q
D[q * q] = [q]
else:
# q is composite. D[q] is the list of primes that
# divide it. Since we've reached q, we no longer
# need it in the map, but we'll mark the next
# multiples of its witnesses to prepare for larger
# numbers
#
for p in D[q]:
D.setdefault(p + q, []).append(p)
del D[q]
def smallest_prime_factor(x):
"""Returns the smallest prime number that is a divisor of x"""
# Start checking with 2, then move up one by one
return next((i for i in gen_primes(int(math.sqrt(x) + 1)) if x % i == 0), x)

How to write a function wrong_prime that takes no arguement and should return the first prime p for which q = 2^p - 1 is not prime

500 years ago it was believed that all numbers q of the form q = 2^p -
1 are prime if p is prime.
Write a function wrong_prime that takes no arguments. It should return
the first prime p for which q = 2^p - 1 is not prime.
Hint: this number should be between 10 and 15.
The code I have come up with is the following but does not work
def isprime(n):
if n < 2:
return False
elif n == 2:
return True
else:
if n % 2 == 0:
return False
for i in range(3,n,2):
if n % i == 0:
return False
return True
def wrong_prime():
for i in range(1,):
q = 2**i-1
if isprime(i) and isprime(q) == False:
print(q)
When inputting wrong_function there is no output
Can anyone help produce a working function?
range(1,) is range(0, 1), i.e. you are only testing 0. If you want an open-ended range, you can use e.g. a while loop with an extra counting variable.
def wrong_prime():
i = 1
while True: # fix loop
q = 2**i-1
if isprime(i) and isprime(q) == False:
return i # return p, not print q
i += 1 # remember to increment manually
Or using next with itertools.count:
import itertools
def wrong_prime():
return next(p for p in itertools.count(1) if isprime(p) and not isprime(2**p-1))
(Of course, given the "Hint" you can also just use a range(10, 16))
Also, note that the function should return the value of p, whereas yours prints q. For testing, call as print(wrong_prime()) to see the value.

Project Euler #3 Python

This is my solution to Project Euler Problem 3. I have written this code for Project Euler but if I put in "49" i get "49". What seems to be the problem?
n = 600851475143
i = 2
while (i * i < n):
while (n % i == 0):
n = n / i
i = i + 1
print (n)
I'm assuming you meant set n = 49.
Your outer while loop checks the condition i * i < n, which is not true for i == 7, so the outer loop breaks as soon as it hits 7. Change the < to <=.
However, your code isn't correct in the first place-- perhaps something like this is what you meant?
n = 600851475143
i = 2
factors = []
while (i <= n):
while (n % i == 0):
n = n / i
factors.append(i)
i = i + 1
print factors
You're printing n you want to print i...
Probably the fastest way to solve it by finding all the prime factors and then return the max.
Brute force solution took me less then 1 sec
I'm assuming you mean n = 49.
Your code isn't right, but the error is small -- change the < to <= and it works for Project Euler #3.
The problem of the code not working for squares such as 49 still remains though. Here is a modified piece of code that should work for squares as well.
n = 49
i = 2
while i * i <= n:
while n % i == 0:
x = n
n = n / i
i = i + 1
if n == 1:
print x
else:
print n
finding factors of N only need to check upto √N.
First basic solution:-
value of N never change
find factors upto √N & store biggest factor.
from math import sqrt
ans = -1
n = input() #or directly put
for i in range(2,int(sqrt(n))+1):
while (n%i==0):
if i > ans:
ans = i
print(ans)
Little optimized solution:-
if we change value of N, it iterate less than previous method.
only need to check % (modulus) of N with primes.
if have prime numbers list, then check/iterate with that only
unless, ignoring even numbers check numbers like 9,15,21... is prime or not, is worthless so...
excluding 2 all prime is odd.
so after check N with 2, check N with only odd numbers.
find factors upto √N & store biggest factor.
when get factor, divide N until N no have that factor
find the next factor do same process, until N become 1 (no have any factors)
from math import sqrt
ans = 2
n = input() #or directly put
while (n%2 == 0):
n /= 2
i = 3
while n > 1:
while (n%i == 0):
ans = i
n /= i
i += 2
print(ans)
find prime factors and return largest obviously
from math import sqrt
def is_prime(n):
if n ==2:return True
if n<2:return False
if n%2==0:return False
for i in range(3,int(sqrt(n))+1,2):
if n%i == 0:
return False;
return True;
n = 600851475143
i = n
while(i>1):
if is_prime(i) and is_prime(i) and n%i==0:
print(i);
break
i = i-1;
Your code is written assuming there are more than one factor, but in the case of n=49, it turns out that it has only one factor that is 7. So you can add a line checking whether it has more than one factor, or if not then it should be printed.

Categories