Problem Statement :
The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime.
There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97.
How many circular primes are there below one million?
My Problem
I have checked through all the code and found that the binary search function is giving a return 1 statement as the output print success. But nothing is added to the final list. Please Help
Program in Python :
from time import time
start = time()
LIMIT = 1000000 # largest limit of the prime numbers
prima = [] # list of primes later to be filled by primes function
# binary search function
def Bsearch(lsta,low,high,search):
if low>high:
return -1
else:
mid = int((low+high)/2)
if search<lsta[mid]:
Bsearch(lsta,low,mid-1,search)
elif search>lsta[mid]:
Bsearch(lsta,mid+1,high,search)
elif search==lsta[mid]:
print("Success!")
return 1
# prime number generating function
# uses sieve of Era** algorithm
# produces correct result tested
def primes(LIMIT):
lsta = {} # temporaty empty dictionary
for i in range(2,LIMIT):
lsta[i] = 1
for i in range(2,LIMIT):
for j in range(i,LIMIT):
if i*j>LIMIT:
break
lsta[i*j] = 0
for i in range(2,LIMIT):
if(lsta[i]==1):
prima.append(i)
primes(LIMIT)
final = []
for item in prima:
x = int(str(item)[::-1])
# real problem here the following statement not inserting any value in final list
if(Bsearch(prima,0,len(prima)-1,x)):
print("Hello!")
print(final)
final.append(item)
print(final)
Quickly generate prime numbers and list out Circular Prime numbers
def primes(max_n):
numbers = range(3, max_n+1, 2)
half = (max_n)//2
initial = 4
for step in xrange(3, max_n+1, 2):
for i in xrange(initial, half, step):
numbers[i-1] = 0
initial += 2*(step+1)
if initial > half:
return [2] + filter(None, numbers)
def rotate(S_list):
S=[]
for i in range(len(S_list)):
S.append(int(S_list[i:]+S_list[:i]))
return set(S)
def circularPrime(limit):
All_primes_in_limit = primes(limit)
circular_prime=[]
reject_list=['0','2','4','5','6','8']
All_primes_in_limit=[i for i in All_primes_in_limit if not any(j in reject_list for j in set(str(i)))]
while All_primes_in_limit:
ShufleSet=rotate(str(All_primes_in_limit[-1]))
PrimesSet=set(All_primes_in_limit)
if not ShufleSet - PrimesSet:
circular_prime+=list(ShufleSet)
All_primes_in_limit=list(PrimesSet-ShufleSet)
circular_prime.sort()
return circular_prime
#for limit value 1000000
print circularPrime(1000000)
This is the fastest possible algorithm for circular prime number listing
Related
I'm new to python and in order to learn I'm trying to solve a problem as an exercise.
N is a integer between [1, 10^9]
K is a list of length <= 40 of random distinct prime numbers that are all equal or less to N.
My code has to find the quantity of number that are <= N that are not divisible by any number of the list K.
I've written the following code:
first_line = input().split()
second_line = input().split()
n = int(first_line[0])
list_of_primes = second_line
all_multiples_set = set()
for i in range(len(list_of_primes)):
prime = int(list_of_primes[i])
# Creates a set of all multiples numbers of this prime that are equal or less than N.
one_multiple_set = set(range(prime ,n if n % prime != 0 else n + prime ,prime ))
# Makes a Union of this set with the previous sets of multiples, thus getting all multiples of a and b.
all_multiples_set = all_multiples_set.union(one_multiple_set)
print(n - len(all_multiples_set))
The first input consist of 2 numbers: N and length of K respectively. (ie. "10 3").
The second input is a series of length of K primes that are less or equal to N. (ie. "2 3 7").
The output should be a integer that represents the quantity of number equal or less than N that are not dividable by any number in list K. (ie. "2" in this case)
I know my code works for some cases, but unfortunately the platform where I found this puzzle does not tell me for which cases my code does not work, it only tells me that it does not work for some cases.
I believe it is a question of memory. Given that 10^9 is a very large number, but it could also be an error that I'm not seeing.
I would appreciate some guidance in how to improve my code or a suggestion of a better approach. It is worth noticing that since this is an exercise, I can not import modules and also since I'm trying to learn, I would appreciate an explanation of why my code is ineficiente.
EDIT:
Execution time is also a factor. The code has 1 second max run time.
On my first try I wrote this code:
linha1 = input().split()
linha2 = input().split()
n = int(linha1[0])
s = linha2
x = len(s)
value_to_add = 0
value_to_subtract = 0
for i in range(1 << x):
single_set = []
multiply = 1
for j in range(x):
if i & (1 << j):
single_set.append(int(s[j]))
for num in single_set:
multiply *= num
if multiply > n:
break
if len(single_set) == 1:
value_to_add += n//single_set[0]
elif len(single_set) > 1:
value_to_subtract += n//multiply
print(n - value_to_add + value_to_subtract)
It also gets the right answer, but it takes to long to run.
Since the list contains distinct prime numbers, this problem can be reduced to finding how many numbers less than or equal to N are divisible by these primes then deduct that number from N.
Since N can be large (10^9) and K is not, you can use inclusion-exclusion principle to find that.
N/x = quantity of numbers less than or equal to N and are divisible by x
N/(x*y) = quantity of numbers less than or equal to N and are divisible by both x and y at the same time.
using inclusion exclusion principle and your sample data:
According to inclusion-exclusion, you add the number to the result when the
list_of_primes = [2, 3, 7]
n = 10
We add these:
10 / 2 = 5
10 / 3 = 3
10 / 7 = 1
-----------
9
Subtract these:
10 / (2 * 3) = 1
10 / (2 * 7) = 0
10 / (3 * 7) = 0
----------------
1
And add this:
10 / (2 * 3 * 7) = 0
--------------------
0
result = 9 - 1 + 0 = 8
n - result = 10 - 8 = 2 <-- this is the answer
You can implement that using a recursive approach as the following:
list_of_primes = [2, 3, 7]
n = 10
k = 3
def get_count(i, num, taken):
if num > n:
return 0
if i == k:
# the case 0 numbers taken
if taken == 0:
return 0
# if odd number of numbers are taken
if taken % 2:
return n // num
# if even number of numbers are taken
return -1 * (n // num)
return get_count(i+1, num * list_of_primes[i], taken+1) + get_count(i+1, num, taken)
print(n - get_count(0, 1, 0))
# 2
From wikipedia:
Generalizing the results of these examples gives the principle of
inclusion–exclusion. To find the cardinality of the union of n sets:
Include the cardinalities of the sets.
Exclude the cardinalities of the pairwise intersections.
Include the cardinalities of the triple-wise intersections.
Exclude the cardinalities of the quadruple-wise intersections.
Include the cardinalities of the quintuple-wise intersections.
Continue, until the cardinality of the n-tuple-wise intersection is included (if n is odd) or excluded (n even).
[Edited]
Be sure to convert to int before sorting:
list_of_primes = list(map(int, input().split()))
I also found a way to optimize the code roughly 2x faster. Note that if in some branch num is multiplied by min prime number from list is larger then N, than there is no need to continue and branch more, since we wouldn't change num as it is already big enough. Therefore, the following code:
list_of_primes = [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]
n = 10 ** 9
list_of_primes.sort(reverse=True)
k = len(list_of_primes)
min_prime = list_of_primes[-1]
def get_count(i, num, taken):
if num > n:
return 0
# if min_prime * num > n then we won't take any new numbers
# thus taken won't change
if min_prime * num > n or i == k:
# the case 0 numbers taken
if taken == 0:
return 0
# if odd number of numbers are taken
if taken % 2:
return n // num
# if even number of numbers are taken
return - 1 * (n // num)
return get_count(i+1, num * list_of_primes[i], taken+1) + get_count(i+1, num, taken)
print(n - get_count(0, 1, 0))
is almost two times faster on the given test than the previous solution: 0.25s vs 0.63s.
Old solution:
I found a way to decrease the depth of the recursion. You should iterate through descending sorted array of prime numbers to faster finish branching, i.e.:
list_of_primes.sort(reversed=True)
Thus in the worst case I improved the time from 5 seconds to 1.2 seconds.
list_of_primes = [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]
n = 10 ** 9
list_of_primes.sort(reverse=True)
k = len(list_of_primes)
def get_count(i, num, taken):
if num > n:
return 0
if i == k:
# the case 0 numbers taken
if taken == 0:
return 0
# if odd number of numbers are taken
if taken % 2:
return n // num
# if even number of numbers are taken
return -1 * (n // num)
return get_count(i+1, num * list_of_primes[i], taken+1) + get_count(i+1, num, taken)
print(n - get_count(0, 1, 0))
It's very easy for your all_multiples_set to grow to a number very close to 10^9, which is going to consume on the order of 40GB of memory -- more than is reasonable on most machines! So you'll need a strategy that doesn't require you to keep track of so many numbers.
Start by getting N and K:
n, _ = map(int, input().split())
k = list(map(int, input().split()))
From there, one possible strategy would be to keep track of only the numbers that might actually match, and prune that number down as you go:
candidates = [c for c in range(1, n + 1) if c % k[0]]
for j in k[1:]:
candidates = [c for c in candidates if c % j]
print(len(candidates))
This has the advantage of getting faster and smaller when you're going through a large K list, but it still has the space problem because you start off with a lot of candidates (e.g. if N is 10^9 and your first value of K is 2, you have 5 billion ints to keep track of, which is better than 10 billion but still too many).
The way to do this without taking up any space at all is to iterate through all the candidates from 1 to N, completely evaluate each one against each element of K, and add 1 to the count if it meets the criteria. That way the only thing you need to keep track of is the count, and not what all the actual numbers are.
print(sum(
1 if all(c % j for j in k) else 0
for c in range(1, n+1)
))
I want to iterate through a list in python, detect prime numbers and then add them to another list.
primes = []
nprimes = []
for j in range(0, len(arr)):
num = arr[j] #my list with numbers to check
if num > 1:
for k in range(2, num):
if (num % k) == 0:
nprimes.append(num)
break
else:
primes.append(num)
else:
print(num, " can't be checked, because its smaller than 1")
I have the problem that numbers are always added which are not prime numbers. Also in general the code does not seem to work properly.
If num % k == 0 is false you can't say it's prime directly you have to wait the whole loop, so move the else with the for loop, it'll be executed of no break has been encountered which means it's prime
you may iterate directly on the values for num in arr
you can stop your loop at sqrt(num) you won't find a new divisor after that
for num in arr:
if num > 1:
for k in range(2, int(num ** 0.5) + 1):
if num % k == 0:
nprimes.append(num)
break
else:
primes.append(num)
else:
print(num, " can't be checked, because its smaller than 1")
For learning purposes, let's play with a different approach. First, I recommend you move your trial division code into its own predicate function is_prime(), that returns True or False, so it can be optimized independently of the rest of your code.
Then, I'm going to have itertools.groupby divide the list into prime and non-prime sequences that we splice onto the appropriate lists:
def is_prime(number):
if number < 2:
return False
if number % 2 == 0:
return number == 2
for divisor in range(3, int(number ** 0.5) + 1, 2):
if number % divisor == 0:
return False
return True
if __name__ == "__main__":
from random import sample
from itertools import groupby
array = sample(range(1, 100), 15)
primes = []
composites = []
for are_prime, numbers in groupby(array, is_prime):
if are_prime:
primes.extend(numbers)
else:
composites.extend(numbers)
print("Numbers:", array)
print("Primes:", primes)
print("Composites:", composites)
OUTPUT
% python3 test.py
Numbers: [91, 87, 10, 2, 11, 24, 21, 12, 46, 61, 15, 32, 57, 22, 5]
Primes: [2, 11, 61, 5]
Composites: [91, 87, 10, 24, 21, 12, 46, 15, 32, 57, 22]
%
There are lots of ways to go about this problem, many of them educational!
Problem
When 32, and select other numbers are inputted, the following error is given:
Traceback (most recent call last):
File "python", line 43, in <module>
IndexError: list assignment index out of range
(Line 43 is extrafactors[i] = factorCheck(i).) However, with other numbers, the code works just fine.
Code
from functools import reduce
n = int(input("Please input a whole number"))
primes = []
def isPrime(x):
if x<2:
return False
for i in range(2,x):
if not x%i:
return False
return True
def factorCheck(n):
x = []
for i in range(1,n):
if n%i==0:
x.append(i)
return x
if isPrime(n) == True:
print("1, ",n)
else:
for i in range (1,n):
if isPrime(i) == True:
if n%i == 0:
primes.append(i)
multiplied = reduce(lambda x, y: x*y, primes)
if multiplied != n:
left = int(n/multiplied)
if isPrime(left) == True:
primes.append(left)
else:
extrafactors = []
extrafactors = factorCheck(left)
while len(extrafactors) > 0:
for i in extrafactors:
if isPrime(i) == True:
primes.append(i)
extrafactors.remove(i)
else:
extrafactors[i] = factorCheck(i)
extrafactors = [item for sublist in extrafactors for item in sublist]
primes = sorted(primes)
print(primes)
Code Explanation
There are two functions defined. One checks if a number is prime, and the other produces a list of factors of a number. First, the program takes in the number inputted by the user. Then, it tests if it is prime, and prints the prime factorization then (1, whatever the number is). If it isn't, it basically finds all primes that are factors of the number and are also prime. The program then multiplies these together, and if they are less than the original number inputted, it finds (prime) factors of the difference and appends them to the list of prime numbers which is printed at the end.
I understand the program may be inefficient, but I understand it how it is written. The line that gives the error replaces a number with a list of factors of that number.
I'm not going to review your code. It's much more complicated than it needs to be.
Here is a simple function for factoring integers. It's not the best way to factor integers, but it's simple and reasonably efficient as long as n isn't too big, less than a dozen digits, say.
def factors(n):
f, fs = 2, []
while f * f <= n:
if n % f == 0:
fs.append(f)
n = n / f
else:
f = f + 1
fs.append(n)
return fs
This problem is easier to do with a recursive function. Recursive functions call themselves. So, basically once we find a factor, we check to see if the number can be factored further, if it can be we append it to the list and keep factoring, if it can't be factored, then we simply append and return.
def factor(numberToFactor, arr=list()):
for i in range(2, numberToFactor // 2 + 1):
if numberToFactor % i == 0:
return factor(numberToFactor/i,arr + [i])
return list(set(arr + [numberToFactor]))
print(factor(32))
I know there are a number of ways to find the first 100 prime numbers but please help me in my approach. I find the value of count to be increasing but for some reason the while loop condition doesn't apply:
count = 0
while(count <= 20):
for i in range(2, 20):
for j in range(2, i):
if i < j:
print("The number",i,"is prime")
elif i % j == 0:
break
else:
print("The number",i,"is prime")
count = count + 1
print(count)
You could use Sieve of Eratosthenes to find the first n prime numbers:
def primes_upto(limit):
prime = [True] * limit
for n in range(2, limit):
if prime[n]:
yield n # n is a prime
for c in range(n*n, limit, n):
prime[c] = False # mark composites
To get the first 100 primes:
>>> list(primes_upto(542))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, ... ,
499, 503, 509, 521, 523, 541]
To find the first n primes, you could estimate n-th prime (to pass the upper bound as the limit) or use an infinite prime number generator and get as many numbers as you need e.g., using list(itertools.islice(gen, 100)).
This is a more simpler code. We have looped all the numbers from 0 to the number until we have printed 100 prime numbers.
n=0
i=0
while n<100:
i+=1
count=1
for j in range(2,i):
if i%j==0:
count=0
break
if count==1:
print(i,end=' ')
n+=1
If one is looking for a mix of efficiency and simple code, Numpy is worth a try. With some fancy indexing, the following code does the job of implementing the sieve of Eratosthenes.
import numpy as np
ns = np.array(range(2,N))
primes = []
last_prime=2
while last_prime:
primes.append(last_prime)
ns = ns[ns%last_prime != 0]
last_prime = ns[0] if len(ns) > 0 else None
print(primes[:100])
Then just adjust N until you do have 100 primes. A good first guess is something in the order of 100*log(100) ~ 460 (coming from the prime number theorem). This will give 88 primes. Increasing N to the value of 600, you will have enough primes.
prime_count=0
n=1
while(True):
count=0
i=2
n+=1
while(i<=n):
if(n==i):
print(n)
prime_count+=1
elif(n%i==0):
break
i+=1
if(prime_count==100):
break
I am attempting to do Project Euler problem #2. Which is:
Each new term in the Fibonacci sequence is generated by adding the previous two
terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed
four million, find the sum of the even-valued terms.
However the terminal window hangs when I use the following code with 4000000. Smaller numbers run ok. Is there something about this code that is really inefficient, hence the lagginess?
n = int(raw_input("Enter the start number: "))
def fib_generator():
a, b = 0, 1
yield 0
while True:
a, b = b, a + b
yield a
def even_sum(fib_seq):
seq = []
seq = [next(fib_seq) for number in range(n)]
seq = [number for number in seq if number % 2 == 0]
return sum(seq)
def start():
fib = fib_generator()
even_sum = even_sum(fib)
print even_sum
start()
You have a bug. You're generating the first 4,000,000 Fibonacci numbers, but the problem statement only asks for those Fibonacci numbers whose values are not more than 4,000,000.
Since the Fibonacci numbers grow exponentially (Fn ~ 1.618n), you're generating some numbers with a very large number of digits (log10 Fn ~ n / 5) and that will take an immense amount of time.
Fix the bug, and you'll be okay.
You just need to add logic to stop when the next fibonacci number exceeds 4000000.
Also, I spy a potential problem with this line:
def start():
fib = fib_generator()
even_sum = even_sum(fib) #<--- right here
print even_sum
It isn't good to have a variable name the same as the function name.
Yes, there is something inefficient in your code, you load a very long list into memory twice, with your two seq = ... statements. Why not try one generator expression rather than two list comprehensions? Also, you could alter your Fibonacci generator to stop at a certain number:
def fib_generator(n):
a, b = 0, 1
while a < n:
yield a
a, b = b, a + b
def even_sum(fib_seq):
seq = (number for number in fib_seq if not number % 2)
return sum(seq)
def start():
n = int(raw_input('Enter max constraint: '))
fib_seq = fib_generator(n)
even_sum1 = even_sum(fib_seq)
print even_sum1
start()
This ran pretty fast for me
lst = []
num1 = 1
num2 = 2
sum = 0
jump = 0
next = 0
while next<4000000:
next = num1 + num2
if next<4000000:
if jump ==0:
num1 = next
jump = 1
else:
num2 = next
jump = 0
if next%2 == 0:
lst.append(next)
for item in lst:
sum+=item
print ''
print "Sum: ",
print sum