I have this code I want to run:
def genPrimes():
primes = [] # primes generated so far
last = 1 # last number tried
while True:
last += 1
for n in primes:
if last % n == 0:
break
else:
primes.append(last)
yield last
n = genPrimes()
How would I implement this to return a list of 100 primes?
This is a generator. If you correct the indentation, you can use it in a for-loop, or use islice to get the first 100 primes:
from itertools import islice
def genPrimes():
primes = [] # primes generated so far
last = 1 # last number tried
while True:
last += 1
for n in primes:
if last % n == 0:
break
else:
primes.append(last)
yield last
primes = list(islice(genPrimes(), 100))
try: [n.next() for x in range(100)]
This code is a bit cryptic. I also don't think it does anything.
Your else is attached to your while which would only execute if you hit a break. Clever but cryptic. However, you initialize your list to [] and then do a loop though it. Looping through an empty list skips the body of the loop, which means the break will never execute. Since the break will never execute, the generator will never yield anything.
Thus, this is an infinite loop that does nothing.
Related
Task: It is necessary to output a chain of words so that the next word begins with the last letter of the previous word.
Input Example: "aac", "cas", "baa", "eeb"
Example output: "eeb", "baa", "aac", "cas"
When using a large number of words (~ 980), the program goes into an endless loop.
I think the problem is here, but I can’t solve it:
for j in range(0,N-U):
if (s[j][0] == words[i][-1]):
searchNextWord(s,j,U)
Code:
def searchNextWord(words,i,U):
global Result
s = [None]*N
if (Result==True):
return
res[U] = words[i]
U += 1
if (U == N):
Result = res[U - 1] == words[i]
if (Result==True):
return
for j in range(0,N-U):
if (j<i):
s[j]=words[j]
else:
s[j]=words[j+1]
for j in range(0,N-U):
if (s[j][0] == words[i][-1]):
searchNextWord(s,j,U)
words=[]
N=int(input())
if (N<1 or N>1000):
exit()
for i in range(N):
new_element = str(input())
words.append(new_element)
res = [None]*N
for i in words:
if (len(i)>10):
exit()
Result = False
for i in range(0,N):
if (Result==False):
searchNextWord(words, i, 0)
if (Result==True):
for i in range(0,N):
print(res[i])
else:
print("NO")
too many for loops man, your program does not go endless but it takes insane amount of time to execute!
use a linked list to do it. It will take more memory per word but it will make the search much more easier. Since you are reordering the input, you will need to consider implementing a browser class that caches the pairs into a variant of a binary tree(where each node contains the start and end of the contained elements. This will reduce the passes you need to perform the search.
#code for SieveOfEratosthenes here
SieveOfEratosthenes=SieveOfEratosthenes(999999)
t = int(input().strip())
for a0 in range(t):
N= input()
prime=set()
for w in range(1,7):
for i in range(0,len(N)):
substring=int(N[i:i+w])
if(N[i:i+w][-1]!=4 and N[i:i+w][-1]!=6 and N[i:i+w][-1]!=8 and N[i:i+w][-1]!=0):
if(len(str(substring))==w and substring in SieveOfEratosthenes):
prime.add(substring)
print(len(prime))
This code is working correctly but timesout for bigger.
Q: How to optimize it?
You do not give examples of your test cases, so we cannot know when it fails.
But here I present a optimized version of your code; at least I think I understood what you are trying to do.
First, I present a implementation of the sieve (not my own invention, the source is in the functions docstring):
def generate_primes():
"""
Generate an infinite sequence of prime numbers.
Sieve of Eratosthenes
Code by David Eppstein, UC Irvine, 28 Feb 2002
http://code.activestate.com/recipes/117119/
https://stackoverflow.com/a/568618/9225671
"""
# 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 True:
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]
q += 1
Python code usually runs faster if you do not use global variables, so I put all the code inside a function. I also:
generate a set (not a list, because set provides faster membership checking) of prime numbers at the beginning.
removed the line
if(N[i:i+w][-1]!=4 and N[i:i+w][-1]!=6 and N[i:i+w][-1]!=8 and N[i:i+w][-1]!=0):
from your code, because it does nothing usefull; N[i:i+w][-1] is the last char of the substring, it has type str and will thus never be equal to an int.
My version looks like this:
def func():
max_prime_number = 10**6
primes_set = set()
for n in generate_primes():
if n < max_prime_number:
primes_set.add(n)
else:
break
print('len(primes_set):', len(primes_set))
while True:
print()
input_str = input('Enter "input_str":').strip()
if len(input_str) == 0:
break
print('Searching prime substring in', input_str)
prime_substrings = set()
for w in range(1, 7):
for i in range(len(input_str)):
n = int(input_str[i:i+w])
sub_str = str(n) # may be shorter than 'w' if it had leading zeros
if len(sub_str) == w:
if n in primes_set:
prime_substrings.add(sub_str)
print('len(prime_substrings):', len(prime_substrings))
I need to write a script that generates random numbers between 1-257000 and stops when a certain number occurs telling me how many numbers it generated so far.
i manged to get this far but can't seem to get it to stop or count
x=1
while x < 257000:
import itertools
import random
def random_gen(low, high):
while True:
yield random.randrange(1, 257000)
gen = random_gen(1, 100)
items = list(itertools.islice(gen, 10))
print items
x = x+1
Thank you so much for your help
Huh. A few flaws (or at least unclear spots) in your code.
You run your loop max 257000 times. Even though the probability is low, there is a chance that you don't hit the number you seek in the loop.
Move your import statements out of your loop, no need to have python check loaded modules each round.
You use a generator for choices of a list (randrange) where you can simply use a randint() call.
You define a closed function within your loop which creates a new function at a new memory address each round.
You slice your results into lists of 10 elements each; is this for printing, or do you actually need your random integers grouped into such lists?
A very simple and straightforward implementation of your described problem could be:
import random
num = 0 # Our counter
certain_number = 123456 # The number we seek
while True: # Run until we break
# Increment for each new step
num += 1
# Generate a single number from the given range
random_number = random.randint(1, 257000)
if random_number == certain_number:
# Break if we hit it
break
print('Hit after {} tries.'.format(num))
>>> Hit after 382001 tries.
First, put your import statements and your function definitons outside your while-loop. That's being super redundant.
>>> def random_gen(low,high):
... while True:
... yield random.randrange(low,high)
...
>>> lucky = 7
>>> rg = random_gen()
>>> rg = random_gen(1,1000)
>>> next(itertools.dropwhile(lambda t: t[1] != lucky, enumerate(rg, 1)))
(811, 7)
>>>
Here's another run, just for fun:
>>> rg = random_gen(1,257000)
>>> n,L = next(itertools.dropwhile(lambda t: t[1] != lucky, enumerate(rg, 1)))
>>> n
22602
>>> L
7
>>>
my while code:
i=0
a = range(100)
while i < range(100):
print i
i += 9
this goes into an infinite loop...may i know why?
is it because an integer is compared to the list?
but what happens when i becomes greater than 99?
shouldnt it come out of the while loop?
below code works fine as expected:
i=0
a = range(100)
a_len = len(a)
while i < a_len:
print i
i += 9
Sadly in Python 2.x, an int is always less than a list (even if that list is empty).
>>> 9 < []
True
What you want to be doing is using the 3-argument form of range so you have a start, a stop and a step, eg:
for i in range(0, 100, 9):
print i
range(100) is a list of integers from 1 to 100 over which you are supposed to iterate. So, len(range(100) = 100. In python 2.x, a list is always greater than an integer. A very simple way to fix this problem is:
i=0
while i < 100: # instead of range(100)
print i
i += 9
I was playing around with the Python shell and I have what I believe is an extremely naive implementation of a function that simply returns the first prime number in a list of 100 randomly generated numbers (whose values are between 0 and 99, inclusive). Code below:
>>> def is_prime(n):
if n < 2:
return False
elif n == 2:
return True
for i in range(2, n):
if n % i == 0:
return False
return True
>>> from random import randint
>>> numbers = []
>>> for i in range(0, 100):
numbers.append(randint(0, 99))
>>> def get_first_prime(values):
temp = []
for i in values:
if is_prime(i):
temp.append(i)
return temp[0]
>>> get_first_prime(numbers)
I want this function to strictly return only the first prime number. My implementation uses a helper list to cache all primes and then simply return the element at the first index. It works, but I'm not convinced it's a good one. I'm sure there is a more efficient way of doing this that does not require scanning through the entire list, but I can't seem to think of one yet.
What are some better alternatives?
def get_first_prime(values):
for i in values:
if is_prime(i):
return i
This way you don't keep searching once you find a prime. The function implicitly returns None if no prime is found.
Yes, you do not even need to generate a list of all the random numbers, you can test each one as they are generated, and return as soon as you've found one.
from random import randint
import math
def is_prime(n):
if n < 2:
return False
elif n == 2:
return True
for i in range(2, int(math.sqrt(n) + 1)):
if n % i == 0:
return False
return True
def get_first_prime(number):
for i in range(number + 1):
n = randint(0, 99)
if is_prime(n):
return n
get_first_prime(100)
You are right. Your code not only has more time complexity (running through all the list elements even after finding the first prime) and space complexity (temp list to hold all the primes) but also stands a risk of throwing IndexError when there are no prime numbers in the list.
So you could mend it in the following manner:
def get_first_prime(values):
for i in values:
if is_prime(i):
return i
Note that when there is no prime in the input the return statement would never get executed that means there is no explicit return; in which case Python returns None. So, if you choose to, you can return the value of your choice at the end of the function outside for loop to indicate 'not found'.
def get_first_prime(values):
for i in values:
if is_prime(i):
return i
return -1
Pythonic way of dealing with this is to raise an Exception and let the caller of the function deal with the exception.
prime = next(filter(isprime, numbers))
See find first element in a sequence that matches a predicate.