Calculating Primes and Appending to a List - python

I've recently started attempting to solve problems on project Euler using python, and have hit this road bump when trying to calculate primes and append them to a list. I have written the following code, but I'm confused as to why it doesn't output anything when I run it.
import math
primes = []
def isPrime(i):
if number<=1:
return False
if number==2:
return True
if number%2==0:
return False
for i in range(3,int(sqrt(number))+1):
if number%i==0:
return False
return True
for i in range (1, 9999999):
if isPrime(i) == True:
primes.append(i)
else:
continue
print(primes)

Try :
import math
primes = []
def isPrime(number):
if number<=1:
return False
if number==2:
return True
if number%2==0:
return False
for i in range(3,int(math.sqrt(number))+1):
if number%i==0:
return False
return True
for i in range (1, 9999999):
if isPrime(i) == True:
primes.append(i)
print(primes)

Try this:
import math
primes = []
def isPrime(number):
if number<=1:
return False
if number==2:
return True
if number%2==0:
return False
for ind in range(3,int(math.sqrt(number))+1):
if number%ind==0:
return False
return True
for i in range (1, 100):
if isPrime(i) == True:
primes.append(i)
else:
continue
print(primes)
To show it working, I print the first 100:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

If you're building up a list of primes, it can be more efficient to use that list as part of your solution.
For example, this loop:
for i in range(3, int(math.sqrt(number)) + 1):
For the prime 1009 will test ~30 numbers but there are only 10 primes less than the square root of 1009 that actually need to be tested. And this difference just keeps increasing.
Using our growing prime list as part of the solution:
primes = [2]
for number in range(3, 9999999 + 1, 2): # only test odd numbers
for prime in primes:
if prime * prime > number: # we're past sqrt, a prime!
primes.append(number)
break
if number % prime == 0: # a composite
break
print(*primes[:10], '...', *primes[-10:])
Nowhere as fast as #ClockSlave's sieve, but will likely finish before many of the other solutions.

The easiest way to do this is to use something called as Sieve. Here's how to get all the primes upto one million.
def mark_sieve(sieve, x):
for i in range(x+x, len(sieve), x):
sieve[i] = False
sieve = [True]*(10**7+1)
for x in range(2, int(len(sieve)**0.5 + 1)):
if sieve[x]: mark_sieve(sieve, x)
The idea is that we initially create a list called sieve and assign all values to True which means that we are for now considering all numbers to 1 million(inclusive) as primes. We will iterate over every number to one million and mark every multiple of it as False in the sieve list. Additionally, to optimize, we iterate only to the square root of 1 million. Why so? Because a number can't have two factors both of which are greater than the square root of the number. So if we divide a number by integers till the ceiling of its square root and its still indivisible, that means its a prime.
So if you want to check if a number is prime, you can simple use sieve[some_number]. If it returns False its not a prime. To get a list of primes you can use [x for x in range(len(sieve)) if sieve[x]]
EDIT
Speed comparisons -
import timeit
import math
def isPrime(number):
if number<=1:
return False
if number==2:
return True
if number%2==0:
return False
for ind in range(3,int(math.sqrt(number))+1):
if number%ind==0:
return False
return True
def mark_sieve(sieve, x):
for i in range(x+x, len(sieve), x):
sieve[i] = False
# Other approaches
time_0 = timeit.default_timer()
primes = []
for i in range (1, 10**6+1):
if isPrime(i) == True:
primes.append(i)
else:
continue
# Sieve Approach
time_1 = timeit.default_timer()
sieve = [True]*(10**6+1)
sieve[0] = False #because we wont consider zero and one as primes
sieve[1] = False
for x in range(2, int(len(sieve)**0.5 + 1)):
if sieve[x]: mark_sieve(sieve, x)
primes_2 = [x for x in range(len(sieve)) if sieve[x]]
time_2 = timeit.default_timer()
time_1-time_0 # 12.423080921173096 seconds
time_2-time_1 # 0.9901950359344482 seconds
For a 100 thousand numbers, using sieves is more than 12 times faster. For a million that ratio becomes 90. Also, when using that many number of numbers, I would advise against appending lists. Instead, initiate a list and then assign values.

Using a conditional list comprehension:
primes = [
i for i in range(1, 9999999)
if i == 2
or i > 2 # Anything less than 2 is not prime.
and i % 2 # No evens (except for 2 above)
and all(i % n for n in range(3, int(i ** 0.5) + 1))]
>>> primes[:10]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
>>> primes[-10:]
[9999889,
9999901,
9999907,
9999929,
9999931,
9999937,
9999943,
9999971,
9999973,
9999991]

Your algorithm to get all prime numbers in [0,9999999] is not very efficient. It need spend a long time to do it so that you cannot see the output when you execute it. It is just because it has not been done. For a faster algorithm, you might check this out

Now it works, I have shortned the numbers to 999
import math
primes = []
def isPrime(number):
if number <= 1:
return False
for i in range(2, int(math.sqrt(number)) + 1):
if number % i == 0:
return False
return True
for i in range(1, 999):
if isPrime(i):
primes.append(i)
print(primes)
[OUTPUT]:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]

Related

Why I cannot see the blind value in my RSA-blind code in Python?

I am trying to enhance the security level of my RSA Python code by adding blind operation, but it does not work, so I cannot do encryption and decryption because I cannot get the blind value. Then I realized I lost the blind value and tried to fix it, but still, there is no change. I can input data but there is no output. How can I fix this problem? Thank you!
Here the relevant code:
import random
import sys
def primeNumber(n, d):
a = random.randint(2, (n - 2) - 2)
x = pow(a, int(d), n)
if x == 1 or x == n - 1:
return True
# square of x
while d != n - 1:
x = pow(x, 2, n)
d *= 2
if x == 1:
return False
elif x == n - 1:
return True
# if is not prime
return False
def isPrime(n):#return True if n prime fall back to primeNumber if uncertain
# 0, 1, -ve numbers not prime
if n < 2:
return False
# low prime numbers
lowPrimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
# if in lowPrimes
if n in lowPrimes:
return True
# if low primes divide into n
for prime in lowPrimes:
if n % prime == 0:
return False
# find number c c * 2 ^ r = n - 1
c = n - 1 # c even bc n not divisible by 2
while c % 2 == 0:
c /= 2 # make c odd
# prove not prime 128 times
for i in range(128):
if not primeNumber(n, c):
return False
return True
def generateKeys(keysize=1):
e = d = N = blank = 0
# get prime nums, p & q
p_input=input("Enter the prime number p:")
q_input=input("Enter the prime number q:")
p= int( p_input)
if p > 1:
for i in range(2, p//2):
if (p % i) == 0:
print(p, "is not a prime number")
sys.exit()
break
q= int( q_input)
if q > 1:
for i in range(2, q//2):
if (q % i) == 0:
print(q, "is not a prime number")
sys.exit()
break
N = p * q # p and q multiplication
totientN = (p - 1) * (q - 1) # totient
# e is coprime with totientN & 1 < e <= totientN
while True:#e
e = random.randrange(2 ** (keysize- 1), 2 ** keysize - 1)
if (CoPrime(e, totientN)):
break
# d is mod inv of e with respect to totientN, e * d (mod totientN) = 1
d = modularInv(e, totientN) #d
return e, d, N,blank
def CoPrime(p, q): #return True if gcd(p, q) is 1 relatively prime
return gcd(p, q) == 1
def gcd(p, q):# euclidean algorithm to find gcd of p and q
while q:
p, q = q, p % q
return p
def egcd(a, b):
s = 0; old_s = 1
t = 1; old_t = 0
r = b; old_r = a
while r != 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
old_t, t = t, old_t - quotient * t
# return gcd, x, y
return old_r, old_s, old_t
def multiplication(keysize,blank,N,e):
blindRSA=0
while True:#create blinder
blindRSA=random.randrange(2 ** (keysize- 1), 2 ** keysize - 1)
if(CoPrime(blank, N)):
break
return blindRSA
def blindRSAalg(blank,blindRSA,e):
blinded=0
blinded=blank*(blindRSA**e)
return blinded
def blindInv(blinded,N):
blind=0
blind=blinded%N
return blind
def modularInv(a, b):
gcd, x, y = egcd(a, b)
if x < 0:
x += b
return x
def encrypt(e, N, msg):
cipher = ""
for c in msg:
# print ("C is that" ,c)
m = ord(c) #string to ascii
print("M is that" ,m)
cipher += str(pow(m, e, N)) + " "
#print("C is that" ,cipher)
return cipher
def decrypt(d, N, cipher):
msg = ""
parts = cipher.split()
for part in parts:
if part:
c = int(part)
msg += chr(pow(c, d, N))
return msg
def main():
print("Run")
keysize = 32
e, d, N,blank= generateKeys(keysize)
msg = input("Enter the message :")
blank=int(input("Enter the blank number:"))
blindRSA= multiplication(keysize,blank,N,e)
blinded =blindRSAalg(blank,blindRSA,e)
blind= blindInv(blinded,N)
enc = encrypt(e, N, msg)
dec = decrypt(d, N, enc)
print("Input message:",msg)
print("e:",e)
print("d:",d)
print("blank:",blank)
print("blinder:",blindRSA)
print("blinded:",blinded)
print("blind:",blind)
print("N:",N)
print("Encryption message:", enc)
print("Decryption message:", dec)
main()

Skip two or more than two iterations in a for loop

I want to skip 2 iterations using continue in for loop. But continue skip only single iteration. Could anyone let me know how to skip two or more iterations?
numbers = [
951, 402, 984, 651, 360, 69, 408, 319, 601, 485, 980, 507, 725, 547, 544,
615, 83, 165, 141, 501, 263, 617, 237, 865, 575, 219, 390
]
for number in numbers:
if number == 237:
continue
print(number)
I want to skip number 360, 263 and 980 too.
Use iterator function iter(numbers) and function next(). They are all built-in.
numbers_to_skip = [237, 360, 263, 980]
numbers_iter = iter(numbers)
for number in numbers_iter:
if number in numbers_to_skip:
next(numbers_iter)
continue
print(number)
If you want to skip n numbers after the match, you could use a counter. For example, if you want to skip any 69 and the two following number (total 3) you could do:
to_skip = 0
for number in numbers:
if number == 69:
to_skip = 3
if to_skip > 0:
to_skip -= 1
continue
print(number)
Here any 69 in the list will reset the counter which may be or not what you want...
Like this?
iter_to_skip = [LIST OF NUMBERS TO SKIP ITERATION]
numbers = [
951, 402, 984, 651, 360, 69, 408, 319, 601, 485, 980, 507, 725, 547, 544,
615, 83, 165, 141, 501, 263, 617, 865, 575, 219, 390
]
for number in numbers:
if number in iter_to_skip:
continue
print(number)
You can explicit create an iterator of the list. But you have to be careful not to throw an StopIteration exception if there are no items left in the iterator to skip.
An example with simpler items to follow the iteration
numbers = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
]
iternums = iter(numbers)
skip = 4
for number in iternums:
if number == 2:
try:
[next(iternums) for _ in range(skip-1)] # skip next iterations
except StopIteration:
break
continue
print(number)
Out:
1 # 2 and three following skipped
6
7
8
9
10

Python prime fibonacci

Prime Fibonnaci
Problem Description
Given two numbers n1 and n2
Find prime numbers between n1 and n2, then
Make all possible unique combinations of numbers from the prime numbers list you found in step 1.
From this new list, again find all prime numbers.
Find smallest (a) and largest (b) number from the 2nd generated list, also count of this list.
Consider smallest and largest number as the 1st and 2nd number to generate Fibonacci series respectively till the count (number of primes in the 2nd list).
Print the last number of a Fibonacci series as an output
Constraints
2 <= n1, n2 <= 100
n2 - n1 >= 35
Input Format
One line containing two space separated integers n1 and n2.
Output
Last number of a generated Fibonacci series.
Timeout
1
Test Case
Example 1
Input
2 40
Output
13158006689
Explanation
1st prime list = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
Combination of all the primes = [23, 25, 27, 211, 213, 217, 219, 223, 229, 231, 32, 35, 37, 311, 313, 319, 323, 329, 331, 337, 52, 53, 57, 511, 513, 517, 519, 523, 529, 531, 537, 72, 73, 75, 711, 713, 717, 719, 723, 729, 731, 737, 112, 113, 115, 117, 1113, 1117, 1119, 1123, 1129, 1131, 1137, 132, 133, 135, 137, 1311, 1317, 1319, 1323, 1329, 1331, 1337, 172, 173, 175, 177, 1711, 1713, 1719, 1723, 1729, 1731, 1737, 192, 193, 195, 197, 1911, 1913, 1917, 1923, 1929, 1931, 1937, 232, 233, 235, 237, 2311, 2313, 2317, 2319, 2329, 2331, 2337, 292, 293, 295, 297, 2911, 2913, 2917, 2919, 2923, 2931, 2937, 312, 315, 317, 3111, 3113, 3117, 3119, 3123, 3129, 3137, 372, 373, 375, 377, 3711, 3713, 3717, 3719, 3723, 3729, 3731]
2nd prime list=[193, 3137, 197, 2311, 3719, 73, 137, 331, 523, 1931, 719, 337, 211, 23, 1117, 223, 1123, 229, 37, 293, 2917, 1319, 1129, 233, 173, 3119, 113, 53, 373, 311, 313, 1913, 1723, 317]
smallest (a) = 23
largest (b) = 3719
Therefore, the last number of a Fibonacci series i.e. 34th Fibonacci number in the series that has 23 and 3719 as the first 2 numbers is 13158006689
Example 2
Input
30 70
Output
2027041
Explanation
1st prime list=[31, 37, 41, 43, 47, 53, 59, 61, 67]
2nd prime list generated form combination of 1st prime list = [3137, 5953, 5347, 6761, 3761, 4337, 6737, 6131, 3767, 4759, 4153, 3167, 4159, 6143]
smallest prime in 2nd list=3137
largest prime in 2nd list=6761
Therefore, the last number of a Fibonacci series i.e. 14th Fibonacci number in the series that has 3137 and 6761 as the first 2 numbers is 2027041
from itertools import permutations
def isPrime(n):
for i in range(2,n):
if n%i==0:
return False
else:
return True
def listPrime(n1,n2):
lis=[]
for ele in range(n1,n2+1):
if isPrime(ele)==True:
lis.append(ele)
return lis
def returnPrime(lis):
r=[]
for ele in lis:
if isPrime(ele)==True:
r.append(ele)
return r
def fibo(mi,ma,c):
f=mi
s=ma
res=[]
res.append(f)
res.append(s)
for i in range(2,c):
next=f+s
res.append(next)
f,s=s,next
return res[-1]
def main(n1,n2):
primeNo=listPrime(n1,n2)
comb=permutations(primeNo,2)
r=[]
for ele in comb:
r.append(int(str(ele[0])+str(ele[1])))
comb2=returnPrime(r)
count=len(comb2)
mini=min(comb2)
maxi=max(com2)
res=fibo(mini,maxi,count)
return res
if __name__=="__main__":
lis=list(map(int,input().split()))
lis[0]=n1
lis[1]=n2
res=main(n1,n2)
print(res)
Please help me write the right solution to the code
Also help me optimize it so it runs in below 1 seconds
Profile in which method most time is spent. A wild guess would be isPrime(..). So try to optimize that.
Speedup of 2 by checking even separately and than only check in the loop only odd numbers.
1b. You can improve this even more by storing a list of the first m primes and
check them up front.
you could keep found primes up to a certain value and every number smaller than the highest of your primes that is not in the set of your primes is no prime.
There are a lot of clever ways to implement isPrime(...) just google it and you will find a vast amount of optimization ideas for it.
def check_prime(x):
if x&1 == 0: return 0
for i in range(3,int(x**0.5)+1,2):
if x%i==0: return 0
return 1
n1,n2 = 30,70
min = 9789
max = 23
count = 0
freq = {}
if n1&1 == 0:
l = [i for i in range(n1+1,n2+1,2) if check_prime(i)]
else:
l = [i for i in range(n1,n2+1,2) if check_prime(i)]
if n1 == 2: l = [2] + l
for x in l:
for y in l:
if x != y:
n = int(str(x)+str(y))
if n not in freq:
if check_prime(n):
freq[n] = 1
if n<min: min = n
elif n>max: max = n
count += 1
while count>1:
min,max = max,min+max
count -= 1
print(min)

get prime numbers from numpy array [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have a numpy array like,
nums = np.array([17, 18, 19, 20, 21, 22, 23])
How do I filter out the prime numbers from this array in a pythonic manner?
I know to do a simple filtering like,
nums[nums > 20] #array([21, 22, 23])
Is there a way to pass a lambda function for filtering?
Expected output: array([17, 19, 23])
The way that I would do it is with gmpy or a 3rd party library who has developed a good primality test algorithm. The Miller-Rabin primality test is generally a very safe (and fast!) bet. If you just want the slow way, you can do:
import numpy as np
import math
def is_prime(n):
if n % 2 == 0 and n > 2:
return False
return all(n % i for i in range(3, int(math.sqrt(n)) + 1, 2))
a = np.arange(1, 10**3)
foo = np.vectorize(is_prime)
pbools = foo(a)
primes = np.extract(pbools, a)
primes # => Output below
array([ 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311,
313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389,
397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563,
569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641,
643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727,
733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821,
823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907,
911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997])
If you want to filter OUT the primes, just call np.invert on the pbools variables. The same would go for any predicate. You can also pass a lambda into vectorize. For example, say we wanted only prime numbers that are also 1 away from being divisible by 5 (for whatever reason).
import numpy as np
import math
def is_prime(n):
if n % 2 == 0 and n > 2:
return False
return all(n % i for i in range(3, int(math.sqrt(n)) + 1, 2))
a = np.arange(1, 10**3)
foo = np.vectorize(lambda x: (not (x + 1) % 5 or not (x - 1) % 5) and is_prime(x))
primes = a[foo(a)] # => Shorthand.... Output below
array([ 1, 11, 19, 29, 31, 41, 59, 61, 71, 79, 89, 101, 109,
131, 139, 149, 151, 179, 181, 191, 199, 211, 229, 239, 241, 251,
269, 271, 281, 311, 331, 349, 359, 379, 389, 401, 409, 419, 421,
431, 439, 449, 461, 479, 491, 499, 509, 521, 541, 569, 571, 599,
601, 619, 631, 641, 659, 661, 691, 701, 709, 719, 739, 751, 761,
769, 809, 811, 821, 829, 839, 859, 881, 911, 919, 929, 941, 971, 991])
If you care of speed and efficiency I would recommend you to use one of the fastest prime sieves and numpy.intersect1d() function:
import numpy as np
def primesfrom2to(n):
# http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
""" Input n>=6, Returns a array of primes, 2 <= p < n """
sieve = np.ones(n//3 + (n%6==2), dtype=np.bool)
sieve[0] = False
for i in range(int(n**0.5)//3+1):
if sieve[i]:
k=3*i+1|1
sieve[ ((k*k)//3) ::2*k] = False
sieve[(k*k+4*k-2*k*(i&1))//3::2*k] = False
return np.r_[2,3,((3*np.nonzero(sieve)[0]+1)|1)]
# generate 100.000 random integers from 1 to 1.000.000.000
a1 = np.random.randint(1, 10**9, 100000)
# generate all primes that are equal or less than a1.max()
primes = primesfrom2to(a1.max())
# print result
print(np.intersect1d(primes, a1))
It appears that you question is not about primes at all, but about how to apply a function to numpy array. I used simple is_odd example. Maybe np.vectorize is what you are looking for:
In [34]: nums = np.array([17, 18, 19, 20, 21, 22, 23])
In [35]: def is_odd(n):
if n % 2 == 1:
return True
return False
....:
In [36]: is_odd_v = np.vectorize(is_odd)
In [37]: nums[is_odd_v(nums)]
Out[37]: array([17, 19, 21, 23]
If I recall correctly np.vectorize is used primarily for convenience, and does not have great performance.
Having a setup like this:
import numpy as np
import math
nums = np.array([17, 18, 19, 20, 21, 22, 23])
So now we create an array that contains all possible integer candidates:
divisors = np.arange(2,int(math.sqrt(np.max(nums)))+1) # Numbers from 2 to sqrt(max(nums))
print(divisors)
# [2 3 4]
Now apply the modulo operation on the array but with a different dimension so we check each number with each divisor:
print(nums[:,None] % divisors[None,:]) # Modulo operation on each element (0 means divisible)
[[1 2 1]
[0 0 2]
[1 1 3]
[0 2 0]
[1 0 1]
[0 1 2]
[1 2 3]]
Now how do we get the primes ... we check if there is no result in the line that is zero:
print(np.min(nums[:,None] % divisors[None,:], axis=1)) # Minimum of the modulo for that element
# [1 0 1 0 0 0 1]
and then create a mask to index them:
print(nums[np.min(nums[:,None] % divisors[None,:], axis=1) > 0]) # So index them
# [17 19 23]
So all you need in the end is:
nums = np.array([17, 18, 19, 20, 21, 22, 23])
divisors = np.arange(2,int(math.sqrt(np.max(nums)))+1)
nums[np.min(nums[:,None] % divisors[None,:], axis=1) > 0]
all the other stuff is just for illustrating what each step is doing.
This is not trivial since it uses broadcasting of 1D arrays into a 2D array but the method should be clear. Let me know if you have any questions.
If you want to optimize this, there is another possibility: The divisors are currently every number between 2 and the sqrt(max(array)) but you don't need to test for all these numbers. If you had a function that returned all primes in that range that would be enough. For example using primesfrom2to of #MaxU's answer a faster possibility is:
nums = np.array([17, 18, 19, 20, 21, 22, 23])
# All prime numbers in the range from 2 to sqrt(max(nums))
divisors = primesfrom2to(int(math.sqrt(np.max(nums)))+1)
nums[np.min(nums[:,None] % divisors[None,:], axis=1) > 0]
but it uses the same mechanism as before but is a bit faster. :-)
If you really want to use a Filter, you can use this:
nums[[i for i in range(len(nums)) if sum([nums[i]%val==0 for val in range(2,nums[i]-1)])==0]]
What does this do?
We search all indexes with prime number by using
[i for i in range(len(nums)) if sum([nums[i]%val==0 for val in range(2,nums[i]-1)])==0]
This basically goes through every value and checks if it is not divisible by any value smaller than itself (ignoring 1)
[i for i in range(len(nums)) #for every index
if sum(#calculate sum of booleans
[nums[i]%val==0 for val in range(2,nums[i]-1)] # check if it is divisble by any value smaller than itself
)==0 #check if the number of divisors is zero

TypeError For Unsupported Operand type 'int' and 'list'

# Primality Testing with the Rabin-Miller Algorithm
import random
def rabinMiller(num):
# Returns True if num is a prime number.
s = num - 1
t = 0
while s % 2 == 0:
# keep halving s while it is even (and use t
# to count how many times we halve s)
s = s // 2
t += 1
for trials in range(5): # try to falsify num's primality 5 times
a = random.randrange(2, num - 1)
v = pow(a, s, num)
if v != 1: # this test does not apply if v is 1.
i = 0
while v != (num - 1):
if i == t - 1:
return False
else:
i = i + 1
v = (v ** 2) % num
return True
def isPrime(num):
# Return True if num is a prime number. This function does a quicker
# prime number check before calling rabinMiller().
if (num < 2):
return False # 0, 1, and negative numbers are not prime
# About 1/3 of the time we can quickly determine if num is not prime
# by dividing by the first few dozen prime numbers. This is quicker
# than rabinMiller(), but unlike rabinMiller() is not guaranteed to
# prove that a number is prime.
lowPrimes = [[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139,
149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,
431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521,
523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619,
631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953,
967, 971, 977, 983, 991, 997]]
if num in lowPrimes:
return True
# See if any of the low prime numbers can divide num
for prime in lowPrimes:
if (num % prime == 0):
return False
# If all else fails, call rabinMiller() to determine if num is a prime.
return rabinMiller(num)
def generateLargePrime(keysize=1024):
# Returns a random prime number of keysize bits in size.
while True:
num = random.randrange(2**(keysize-1), 2**(keysize))
if isPrime(num):
return num
I am creating a Python program that will tell you if a number is prime or not. It is basically the Rabin Miller Algorithm, but on line 60, my program stops and I get the error:
TypeError: unsupported operand type(s) for %: 'int' and 'list'.
This is line 60:
lowPrimes = [[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, ...]]
What am I doing wrong?
Your lowPrimes variable is a list of lists, so when you say for prime in lowPrimes, prime is a list, so you can't modulus an int by a list. Try changing lowPrimes = [[...]] to lowPrimes = [...] (remove one layer of brackets).
The error message is pretty instructive here. It's saying that you are trying to apply the % operator to an int and a list. Since you also have the line number you can see the expression it's referring to and that prime must have been a list.
Your lowPrimes array is defined in a wrong way. You want it to be a list of numbers, but instead it is a list of lists of numbers (outer list containing only a single element). This causes the error you see when you iterate over all the elements of lowPrimes and check if your number is divisable by that element of lowPrimes. To fix it, remove outer square brackets:
lowPrimes = [[2, 3, 5, 7, 11, 13, 17, 19, ... 997]]
=>
lowPrimes = [2, 3, 5, 7, 11, 13, 17, 19, ... 997]

Categories

Resources