I am building a prime generator (I know, another one and probably not a very good one at that, but that is for another question.) I am using a dictionary for my collection of primes and ignoring composites by dividing by the previous primes. However it doesn't seem to be iterating properly in the final stage of the function and I get a number of incorrect results. isWhole is a self explanatory call to another function. This is my code where x = the number of primes to be generated:
def prime_generator(x):
count = 2
counter = 2
p = {1: 2}
while len(p) <= x:
if count % 2 == 0:
count += 1
continue
test1 = (math.sqrt(count))
if isWhole(test1) == True:
count += 1
continue
for k, a in p.items():
if count % a == 0:
break
else:
p[ counter ] = count
counter += 1
break
count += 1
return p
Your design intent is not entirely clear, but you may be intending to have the else clause apply to the for loop rather than the if statement. Try un-indenting the entire else clause so that it only runs if the loop terminates without hitting a break.
Related
Ok i wrote this in python then rewrote because i don't like if else statements.
the first version worked perfectly. my second one failed and ended up taking more lines than my first version. my question is, am i just stupid? is there a better way to do this or should i just accept the need for if else statement?
sorry for the code dump, i am going mad
first attempt
#number we are starting with
num = 1
#what we are going to apply equation loop to
result = num
#how many times goes through equation loop before reaching 1
count = 0
# list of numbers used in equation loop
num_in_loop = [result]
#end equation loop function.
running = True
# equation loop
def eqation_loop(running, num_in_loop, count, num, result):
while running == True:
if (result % 2) == 0:
result = result /2
count +=1
num_in_loop.append(result)
elif result == 1.0:
print(num, "took", count ," loops to get to 1: numbers in loop = ", num_in_loop, file=open('3x+1/result.txt','a'))
num +=1
print(num)
result = num
num_in_loop = [result]
count = 0
elif num == 100:
running = False
elif (result % 2) != 0:
result = result * 3 + 1
count +=1
num_in_loop.append(result)
eqation_loop(running, num_in_loop, count, num, result)
second attempt:
#number we are starting with
num = 1
#what we are going to apply equation loop to
result = num
#how many times goes through equation loop before reaching 1
count = 0
# list of numbers used in equation loop
num_in_loop = [result]
limit = int(input("range you want to try: " ))
def update_var(num_in_loop,result,count):
count +=1
num_in_loop.append(result)
return equation_loop(limit,num, result)
def reset_var(num_in_loop, count, limit,num, result):
print(num, "took", count ," loops to get to 1: numbers in loop = ", num_in_loop, file=open('3x+1/test.txt','a'))
num +=1
result = num
num_in_loop = [result]
count = 0
return equation_loop(limit,num, result)
def equation_loop(limit,num, result):
if num == limit:
return
elif result == 1:
return reset_var(num_in_loop, count, limit,num, result)
elif (result % 2) == 0:
result = result /2
return update_var(num_in_loop,result,count)
elif (result % 2) != 0:
result = result *3 +1
return update_var(num_in_loop,result,count)
equation_loop(limit,num, result)
You can't write this without any if/else statements (okay maybe if you really know what you're doing you technically can by severely abusing while, but you shouldn't), but here's a simplified-down version that hopefully contains some useful examples of how to make your code easier to write (and read!):
def equation_loop(num: int) -> list[int]:
"""
Repeatedly applies the magic equation trying to
reach 1.0, starting with num. Returns all the results.
"""
nums = [num]
while True:
if num == 1:
return nums
if num % 2:
num = num * 3 + 1
else:
num = num // 2
nums.append(num)
for num in range(1, 100):
results = equation_loop(num)
print(f"{num} took {len(results)} loops to get to 1: {results}")
A key thing here is that you don't need so many variables! A single loop only needs its starting point (num) and only needs to return the list of results (from which you can get the count, since it'll be the length of the list). Reducing the number of redundant variables eliminates a lot of unnecessary lines of code that are just copying state back and forth. Passing a value like running = True is unnecessary when it will always be True until it's time to end the loop -- instead just use while True: and return or break when you're done.
The big takeaway is that if you have two variables that always have the same value (or even two values that are always related in exactly the same way, like a list and its length), you probably just need one of them.
You can also simplify the code by separating the two nested loops -- for a given num you want to loop until the number reaches 1, so that's one loop. You also want to loop over all the nums up to 99 (it took me a while to even figure out that that's what the code was doing; I had to run it and look at the output to see that some of those extra pieces of state were serving to implement nested loops inside a single loop). Doing those in two different loops makes it easy, and you can put one of them in a nice neat function (I used your equation_loop name for that, although it does less work than your original version does) that takes the starting num and returns the list of results for that starting point. That simple function can then be called in an even simpler for loop that iterates through the nums and prints the results for each one.
Note that I kept everything as ints by using int division (//) -- testing floats for exact equality is often dangerous because floating point numbers aren't exactly precise! Your equation is always operating with integer values (because you only divide by two if it's an even number) so it makes more sense to use int division and not even worry about floating point values.
def prime_count(a, b):
for i in range(a,b):
if i % 2 != 0:
return sum(i)
else:
return 0 "
I am a beginner programmer, I have been practicing on some challenges on Edabit, small problems but that require some thinking (for me).
I am trying to count how many prime numbers are on a and b, they are already integers and there is no user input.
I am not very good at loops yet and thought this was going to be a good challenge to practice, what am I doing wrong? I keep getting int object is not iterable
If reference need, here is the link for the challenge.
Link : https://edabit.com/challenge/6QYwhZstMuHYtZRbT
it is an interesting problem that you are solving. You will have to run two-loops here. One to iterate from a to b and the inner loop to check if each element in a -->b is prime or not (the inner loop should run from 2 to j in [a,b).
def primecheck(a,b):
printlist=[]
if a > 1:
for i in range(a,b+1):
for j in range(2,i):
if i % j == 0:
break
else:
printlist.append(i)
if len(printlist) == 0:
return 0
else:
return len(printlist), printlist
Try this out.
As people say in the comment section, calling sum() is what's causing an error.
But, even if you somehow got that part right, you wouldn't quite get what you want. Maybe you were just trying a simple for loop to check if numbers are odd...?
Anyway, I normally like using Sieve of Eratosthenes to generate prime numbers because it's simple.
def sieve_of_eratosthenes(start, end):
if start > end:
raise AssertionError
# end = end + 1 # If end is inclusive, then uncomment this line.
if end < 2:
return 0
sieve = [i for i in range(2, end)] # Initialize an array of number from 2 to end.
size = len(sieve)
p = 2 # Initial prime.
count = 0
# This block implements Sieve of Eratosthenes.
while count < size:
for i in range(count, size):
num = sieve[i]
if num != p and num % p == 0:
sieve[i] = 0
if count == size-1:
break
count += 1
while sieve[count] == 0:
count += 1
if count == size-1:
break
p = sieve[count] # Update the next prime.
# This block calculates the numbers of primes between start and end.
num_of_primes = 0
for p in sieve:
if p == 0 or p < start:
continue
num_of_primes += 1
print(sieve)
return num_of_primes
sieve_of_eratosthenes(1, 100) # This should return 25.
I'm a absolute beginner, and when I made a function to count the number of even ints on a given list, it didn't went as expected, and I can't see where I'm doing it wrong.
nums = [2,2,4,4,5,6,7,8,9]
def count_even(nums):
for number in nums:
num = 0
if number % 2 == 0:
num += number
return num
else:
continue
The output is:
count_even(nums)
2
It stops on nums[1] for some obscure reason.
Or it just prints the first "2" and adds it, and I don't know how to fix it, yet.
You have three problems here.
You're setting num = 0 every time through the loop, instead of just once at the start. So you're only going to get the very last count that you do.
You're doing num += number, instead of num += 1, so instead of counting the even numbers, you're adding them.
You're doing a return num as soon as the first even number is found, instead of only at the end of the function, after the loop. (And that also means that if there are no even numbers, instead of returning 0, you return None).
While we're at it, you don't need else: continue, because continuing is already what happens by default when you fall off the end of a loop.
Anyway, this means it's not stopping at nums[1], it's stopping at nums[0]—but it's adding 2 instead of 1 there, which makes things confusing. (It's always fun when bugs interact like that. Even more fun when they happen to exactly cancel out for your test case, like if you did nums = [6,2,4,4,5,6,7,8,9] and got back 6 and thought everything was working…)
So:
def count_even(nums):
num = 0
for number in nums:
if number % 2 == 0:
num += 1
return num
Your function stops on nums[1] because the return keyword exits the function and returns num (which is set to 0 + number). If you want to print out the sum of all the even numbers in nums you could move the return statement to the end and take the num = 0 expression out of the for loop (because it will reset to 0 after each iteration), like this:
def count_even(nums):
num = 0
for number in nums:
if number % 2 == 0:
num += number
else:
continue
return num
Also, your else statement is redundant here, so you could simply remove it, leaving you with the following:
def count_even(nums):
num = 0
for number in nums:
if number % 2 == 0:
num += number
return num
And you could simplify that further to:
def count_even(nums):
evens = [number for number in nums if number % 2 == 0]
return sum(evens)
Another solution:
def count_even(nums):
return len([i for i in nums if i % 2 == 0])
There are a couple of problems in your code:
Your num needs be defined outside the loop, so you can count every even number found. If you define it inside the loop, it resets to 0 every iteration.
When you find an even number, you increment it towards the counter num. You need to instead increment num by 1.
You return immediately when a even number is found, this means the function exits on the first even number. You instead want to return the total num at the end.
You have an unnecessary continue in the else block. If a uneven number is found, simply ignore it.
Which these suggestions, you could implement your code like this:
nums = [2,2,4,4,5,6,7,8,9]
def count_even(nums):
num = 0
for number in nums:
if number % 2 == 0:
num += 1
return num
print(count_even(nums))
# 6
I am trying to put together a simple program which could work out n prime numbers. I would like to do this by using a nested for loop, where one would go through the numbers, and another would divide that number by all of the numbers up to it to see if it would be divisible by anything.
The problem I am having is that in the main for loop, I need to start it at 2, seeing as 1 would mess up the system and I don't want it to be considered a prime. For the loop to have a starting number however, it also needs an ending number which is difficult in this instance as it is hard to generate the largest prime that will be needed prior to the loop working.
Here's the program that I am using right now. Where I have marked X is where I need to somehow put an ending number for the For Loop. I guess it would be much simpler if I let the For Loop be completely open, and simply take out anything that '1' would produce in the loop itself, but this feels like cheating and I want to do it right.
check = 0
limit = int(input("Enter the amount of Prime Numbers"))
for i in range(2,X):
check = 0
if i > 1:
for j in range(2,i):
if (i % j) == 0:
check = 1
if check == 0:
print (i)
Thanks for your help!
You can step through an unlimited amount of numbers using a generator object.
Insert the following somewhere near the top of your code:
def infinite_number_generator(initial_value=2):
""" Generates an infinite amount of numbers """
i = initial_value
while True:
yield i
i += 1
What this does is it creates a function for constructing generator objects that "pause" whenever they reach the yield statement to "yield" whatever value is specified by the yield command, and then continue to execute from the next line beneath the yield statement.
Python's own range function is itself an example of a generator, and is roughly equivalent to (ignoring the step argument and other peculiarities)
def range(start, end):
i = start
while i < end:
yield i
i += 1
So your program would then look like this:
def infinite_number_generator(initial_value=2):
""" Generates an infinite amount of numbers """
i = initial_value
while True:
yield i
i += 1
check = 0
limit = int(input("Enter the amount of Prime Numbers"))
for i in infinite_number_generator():
check = 0
for j in range(2,i):
if (i % j) == 0:
check = 1
if check == 0:
print (i)
if i == limit:
break
I should also point out that the code you provided is buggy - it will never stop printing because there's no checking whether you've found your limit number of primes yet or not.
This should do what you want.
check = 0
limit = int(input("Enter the amount of Prime Numbers"))
counter = 0
i = 2
while counter < limit:
check = 0
if i > 1:
for j in range(2,i):
if (i % j) == 0:
check = 1
if check == 0:
counter += 1
print (i)
i += 1
In your code you start i with 2 and always increment by 1, so the i will always remain greater than 1, therefore the test if i > 1 is useless.
For efficiency you can stop the check at the square of i or i/2 (no divisors in [i/2 + 1, i[ ).
you can update your code as follow:
n = int(input("Enter the amount of Prime Numbers: "))
FoundPrimes = 0
i = 2
while FoundPrimes < n:
isPrime = True
for j in range(2,1 + i//2):
if (i % j) == 0:
isPrime = False
if isPrime:
FoundPrimes += 1
print(i, end = '\t')
i += 1
def countPrimes(self, n):
if n <= 1:
return 0
if n == 2:
return 1
count = 0
counted = [2, ]
for num in xrange(3, n+1, 2):
for c in counted:
if num % c == 0:
continue
count += 1
counted.append(num)
return count
I am writing a code for the solution of primes counting problems. I used counted as an array storing for primes that have been examined and use them for the examination for the next prime. I tried using continue to drop out the inner for loop then count += 1 and counted.append(num) would not be executed once the num is found not a valid prime. However, I met implementing problem here, as the continue statement would take me to another c instead of another num.
If I understand your question correctly, you want to know how to break the inner c loop, avoid the other code, and continue with another num. Like the other answers, you want to make use of break with some smart booleans. Here's what the loop might look like:
for num in xrange(3, n+1, 2):
next_num = False
for c in counted:
if num % c == 0:
next_num = True
break
if next_num:
continue
count += 1
counted.append(num)
This way, if you encounter a num that is divisible by c, you break out of the inner c loop, avoid adding num to the counted list.
It doesn't make a ton of sense to accumulate a count and a list of primes as you go. Introduces the chance for a mismatch somewhere. I've massaged the code a bit, with some more descriptive variable names. It's amazing how clear names can really make the algorithm make more sense. (At least for me it does)
def primesUpTo(n):
primes = []
if n > 1:
primes.append(2)
for candidate in xrange(3, n+1, 2):
for prime in primes:
candidate_is_prime = candidate % prime
if not candidate_is_prime: # We're done with this inner loop
break
if candidate_is_prime:
primes.append(candidate)
return primes
print len(primesUpTo(100))
Try using break instead of continue. See the documentation here. Basically break takes you out of the smallest enclosing loop, spitting you back into your higher-level loop for its next iteration. On the other hand, continue just jumps you on to the next iteration of the smallest closing loop, so you wouldn't go out to the higher-level loop first.