Check Prime Number, in python. logic confusion - python

I found this code in a website for checking prime number
def isPrime(number):
if (number <= 1):
return False
elif (number <= 3):
return True
elif (number % 2 == 0 or number % 3 == 0):
return False
i = 5
while(i * i <= number):
if (number % i == 0 or number % (i + 2) == 0):
return False
i += 6
return True
but I can't understand the logic of if statement under while loop, that is if (number % i == 0 or number % (i + 2) == 0)
why need i+2??? when i is even, i+2 is also even and odd while i is odd. So, why need to check for i+2???

Except for 2 and 3, all prime numbers are of the form 6n±1. This code checks for 2 and 3 explicitly and then checks higher numbers in pairs: 6n-1, 6n+1, starting with 5. So it checks 5, 7 then 11, 13 then 17, 19 and so on. It steps 6 between pairs and steps 2 within each pair. Doing it this way avoids ever having to check multiples of 2 or 3.

i starts from 5, so adding 2 means taking in count only evens numbers.
It makes the check faster.

If you want to find out if a number is prime or not, here is a short sample
# Check if a positive integer number is a prime number. Check only till square root +1.
import math
def isPrime(n):
if ( n > 3 ):
if (n % 2 == 0):
return False
for i in range(3, math.isqrt(n), 2):
if (n % i == 0):
return False
return True
else:
return True

Related

Recursion for checking an occurrence of a certain digit (no loops only recursion required)

This is my code:
def helper_number_of_ones(n:int, counter:int)->int:
if n == 1:
counter += 1
return counter
else:
if n % 10 == 1:
counter += 1
if n // 10 == 1:
counter += 1
return helper_number_of_ones(n-1,counter)
def number_of_ones(n: int) -> int:
count = 0
return helper_number_of_ones(n,count)
My code basically checks for the number of digit one occurrences, throughout all numbers between n and 1, for example n=13 will output 6 for 6 ones occurrences, the only problem it doesn’t work
properly for numbers bigger than 100? Thanks in advance
Your code takes into consideration two possibilities:
The ones digit is 1 (if n % 10 == 1)
The tens digit is 1 (if n // 10 == 1)
This is enough for numbers up to 99, but fails for higher numbers.
I would suggest to break your function into two separate functions: one that counts the number of occurences of 1 in a single number, and another that does that for a range of numbers (using the first one of course).
It is because of how you calculate counter
...
if n % 10 == 1:
counter += 1
if n // 10 == 1:
counter += 1
...
For example, if n = 100, it will fail both ifs. You can make a function that calculates the number of 1 in a number recursively.
def num_of_one(number):
if number == 0:
return 0
else:
return ((number % 10) == 1) + num_of_one(number // 10)
Then make another function to calculate it over the range.
def range_num_of_one(max_num):
if max_num == 1:
return 1
else:
return num_of_one(max_num) + range_num_of_one(max_num - 1)

List of conditions

I wanted to make a list of conditions for if. I wanted to make a program that would find very high prime numbers. I don't want to write: number % 2 == 0 or - for every number that I divide with. If you know how to make a list of conditions or know how to easier get high prime numbers using yield please give me a hint.
def very_high_prime_numbers_generator():
number = 0
while True:
number = yield
if not (number % 2 == 0 or number % 3 == 0 or number % 7 == 0 or number % 5 == 0 or number % 11 == 0 or number % 17 == 0 or number % 19 == 0 or number % 13 == 0):
print(number)
number_generator = very_high_prime_numbers_generator()
number_generator.send(None)
for i in range(1000,10000):
number_generator.send(i)
You can use a nested loop or any or all to test the divisibility of the number against all those values:
if not any(number % k == 0 for k in (2, 3, 5, 7, 11, 13, 17, 19)):
print(number)
Of course, this still tests only those values, which will not be enough for "very high prime numbers". Instead, you could keep track of the prime number generated so far an test against all of those:
def very_high_prime_numbers_generator():
primes = []
number = 2
while True:
if not any(number % p == 0 for p in primes):
yield number
primes.append(number)
number += 1
number_generator = very_high_prime_numbers_generator()
for _ in range(100):
print(next(number_generator))
(This could be further enhanced by stopping once k**2 > number, e.g. using itertools.takewhile, and only testing odd numbers above 2.)
Also note that your "generator" was rather odd. By using send to set the value of number and then printing inside the function, your "generator" behaved rather like a regular "check if this number is prime" function than a proper generator. The above also fixes that.
This seems to be what you're trying to do although as others have pointed out it's far from efficient.
def find_prime(number, previous_primes):
for value in previous_primes:
if number % value == 0:
return False
return True
known_primes = [2, 3, 5, 7]
for i in range(8, 1000):
is_prime = find_prime(i, known_primes)
if is_prime:
known_primes.append(i)
I would advise having a look here.
a possible solution (yet not that efficient) for printing primes might be as described by Eli Bendersky, in the above link:
import math
def main():
count = 3
while True:
isprime = True
for x in range(2, int(math.sqrt(count) + 1)):
if count % x == 0:
isprime = False
break
if isprime:
print count
count += 1

Number 2 recognized as prime - explaining 2 modulus

Can someone please explain why number 2 is also added to the list of prime numbers in the code below?
As the function below should only recognize a number as prime when there is at least 1 number with modulus not equal to 0.
As
2 % 0 = 0
2 % 1 = 0
That is why it should not be included, right?
def isprime(num1):
for i in range(2, num1):
if (num1 % i) == 0:
return False
return True
def getprimes(max_number):
list_of_primes = []
for i in range(2, max_number):
if isprime(i):
list_of_primes.append(i)
return list_of_primes
def main():
max_num_to_check = int(input('Enter the max limit: '))
list_of_primes = getprimes(max_num_to_check)
for i in list_of_primes:
print(i)
main()
As the function below should only recognize a number as prime when there is at least 1 number with modulus not equal to 0
It seems like you misunderstood how the prime check works. The isprime method actually checks whether there is no number with a modulus equal to zero. Also, it only checks relevant numbers, and that does not include 0 and 1, since the modulus of any number with 1 is zero, and the modulus with 0 is actually not defined.
In the case of 2, the function will check all numbers in range(2, 2), which is empty, thus it (correctly) returns True. The function could be rewritten to this, maybe that's clearer:
def isprime(num1):
return not any((num1 % i) == 0 for i in range(2, num1))

Python: Code to find a number where first N digits are divisible by N (from 0-9)

I've been trying to write a recursive solution to a program to find a number where first N digits are divisible by N.
As an example: 3816547290, 3 is divisible by 1, 38 is divisible by 2, 381 is divisible by 3 and so on...
My recursive solution works fine while going "into" the recursion, but has issues when the stack unwinds (i.e. I don't specifically know how to backtrack or take steps on the way out
ARR = [0]*10
ARR[0] = 1 #dummy entry
def numSeq(pos, num):
if all(ARR):
print num
return True
if (pos>0) and (num%pos) != 0:
return False
for i in xrange(1,10):
if ARR[i] == 1:
continue
new_num = num*10 + i
if new_num%(pos+1) == 0:
ARR[i] = 1
numSeq(pos+1,new_num)
The problem with this code seems to be that it follows the number generation correctly while going into the recursion...so it correctly generates the number 123654 which is divisible by 6 and follows first N digits being divisible by N, but after it fails to find any further digits from 7-8 or 9 that divide 7, i don't get the next set of steps to "reset" the global ARR and begin from index 2, i.e. try 24xxxx,and eventually get to 3816547290
Thanks in Advance for your help!
EDIT: One condition I'd forgotten to mention is that each digit must be used exactly once (i.e. repetition of digits is disallowed)
2nd EDIT:
I was able to finally apply proper backtracking to solve the problem...this code works as is.
ARR = [0]*10
def numDivisibile(num,pos):
if all(ARR):
print num
return True
for i in xrange(0,10):
if ARR[i] == 1:
continue
new_num = num*10+i
#check for valid case
if new_num%(pos+1) == 0:
ARR[i] = 1
if numDivisibile(new_num, pos+1):
return True
#backtrack
ARR[i] = 0
return False
print numDivisibile(0, 0)
To generate all 10 digits integers where the first n digits are divisible by n for each n from 1 to 10 inclusive:
#!/usr/bin/env python3
def generate_ints_nth_digit_divisible_by_n(n=1, number=0):
number *= 10
if n == 10:
yield number # divisible by 10
else:
for digit in range(not number, 10):
candidate = number + digit
if candidate % n == 0: # divisible by n
yield from generate_ints_nth_digit_divisible_by_n(n + 1, candidate)
print("\n".join(map(str, generate_ints_nth_digit_divisible_by_n())))
Output
1020005640
1020061620
1020068010
...
9876062430
9876069630
9876545640
To get numbers where each digit occurs only once i.e., to find the permutations of the digits that satisfy the divisibility condition:
def divisibility_predicate(number):
digits = str(number)
for n in range(1, len(digits) + 1):
if int(digits[:n]) % n != 0:
return n - 1
return n
def generate_digits_permutation(n=1, number=0, digits=frozenset(range(1, 10))):
# precondition: number has n-1 digits
assert len(set(str(number))) == (n - 1) or (number == 0 and n == 1)
# and the divisibility condition holds for n-1
assert divisibility_predicate(number) == (n - 1) or (number == 0 and n == 1)
number *= 10
if n == 10:
assert not digits and divisibility_predicate(number) == 10
yield number # divisible by 10
else:
for digit in digits:
candidate = number + digit
if candidate % n == 0: # divisible by n
yield from generate_digits_permutation(n + 1, candidate, digits - {digit})
from string import digits
print([n for n in generate_ints_nth_digit_divisible_by_n()
if set(str(n)) == set(digits)])
print(list(generate_digits_permutation()))
Output
[3816547290]
[3816547290]
In your function, you never do return numSeq(...), this seems like causing the issue.
If you want to have a iterative solution, you can check the following:
def getN(number):
strNum = str(number)
for i in range(1, len(strNum)+1):
if int(strNum[:i]) % i != 0:
return i-1
return i
print getN(3816)
print getN(3817)
print getN(38165)
Output:
4
3
5
We can modify your recursive function a little to try different possibilities. Rather than have a global record (ARR) of used positions, each thread of the recursion will have its own hash of used digits:
def numSeq(pos, num, hash):
if pos != 1 and num % (pos - 1) != 0: # number does not pass the test
return
elif pos == 11: # number passed all the tests
print num
elif pos == 5:
numSeq(pos + 1,10 * num + 5,hash) # digit is 5 at position 5
elif pos == 10:
numSeq(pos + 1,10 * num,hash) # digit is 0 at position 10
else:
k = 2 if pos % 2 == 0 else 1 # digit is even at even positions
for i in xrange(k,10,2):
if hash & (1 << i): # digit has already been used, skip it
continue
numSeq(pos + 1,10 * num + i,hash | (1 << i))
numSeq(1,0,0) # 3816547290

Prime number generator is not working Python

What I want to do is:
create a "list" of odd numbers
then test if they are prime
the test will be done with multiples up to half of the value of the odd number hence halfodd
put the prime number into a list
print that list
however my result is a list of numbers from 1 to 1003 that skip 3, 4, and 5
Is there a semantic error here?
#Prime number generator
def primenumber():
primelist = [1, 2]
num = 3
even = num%2
multi = 0
result = 0
while len(primelist) < 1000:
if even != 0:
oddnum = num
i = 2
halfodd = ((oddnum + 1)/2)
while i < halfodd:
i =+ 1
multi = oddnum%i
if multi == 0:
result += 1
if result != 0:
primelist.append(oddnum)
prime_num = oddnum
num += 1
print primelist
primenumber()
if result != 0:
Since result is (supposed to be) a count of how many factors you found, you want
if result == 0:
You're also not resetting result when you advance to a new candidate prime, you never recompute even, and if you did, you'd be considering the odd numbers twice each.
This should work:
def primenumber():
primelist = [1, 2]
candidate = 3
while len(primelist) < 1000:
isCandidatePrime = True
if (candidate % 2 == 0): # if candidate is even, not a prime
isCandidatePrime = False
else:
for i in range(3, (candidate+1)/2, 2): # else check odds up to 1/2 candidate
if (candidate % i == 0): # if i divides it, not a prime
isCandidatePrime = False
break
if (isCandidatePrime):
primelist.append(candidate)
candidate += 1
print primelist
I think there are several improvements (check only numbers less than or equal to the square root of the candidate, only check prime numbers, not all numbers less than the square root of the candidate) but I'll leave that alone for now.

Categories