I'm trying to implement something similar to Sieve of Eratosthenes. I want to remove all non prime numbers in a given range from the set, and sum up all the prime number to the given number.
number_set = set(list(range(1, given_number)))
sum_number = 0
for num in number_set:
if isPrime(num):
sum_number += num
prime_set = set(list(range(0, big_number, num)))
number_set -= prime_set
print(sum_number)
Obviously I got the error -
Set changed size during iteration
I'm new to python so the syntax is unfamiliar. As far as I understood from other threads, I can use dictionary and use the for loop on number_set.keys() (right?), but I wanted to ask, is it possible to correct this for loop?
You must stop itering over the modified iterator.
My approach is to restart the iteration after the modification, try to modify the set such as every already processed value is not re-processed, and maybe call it a day.
The exception you are having is just a limitation about sets not liking being iterated over and modified at the same time.
number_set = set(list(range(1, given_number)))
sum_number = 0
done = False
while not done:
for num in number_set:
if isPrime(num):
sum_number += num
prime_set = set(list(range(0, big_number, num)))
number_set -= prime_set
break
done = True
print(sum_number)
Disclaimer: Script might need adjustments on you part, I'm just illustrating the logic
Related
I'm trying to make a program that finds the perfect number.(Perfect number=The sum of its divisors except itself is a number equal to itself.)And I want to add one more thing. Firstly I want to define an empty list and put the perfect numbers in it.But When I run the programm I didn't take the right throughput.How can I solve this problem.
My cods
def perfect(number):
total = 0
for i in range(1,number):
if number % i == 0:
total += i
return total
perfect_number_set = []
for i in range(1,1001)
if perfect(i):
perfect_number_set += [perfect(i)]
print(perfect_number_set)
print(i)
The output of the codes I wrote
[True]
6
[True,True]
28
[True,True,True]
You have following issues in your code:
Your implementation of perfect method is incorrect. You need to return True/False if a number is perfect. You are returning the total which is not correct.
Missing colon : in the for loop
def perfect(number):
total = 0
for i in range(1,number):
if number % i == 0:
total += i
return total == number
perfect_number_list = []
for i in range(1,1001):
if perfect(i):
print(i)
perfect_number_list.append(i)
print(perfect_number_list)
There is a difference between set and a list in python. You have used a list.
Set contains only unique entries.
Best practice tip:
defining a list use :
list_name = list()
Better way of adding items to as list by using it's method
list_name.append(list_item_to_add)
Another thing is that returning a number and checking it in if without any condition is not readable. Change it to:
if perfect(i) != 0:
(Altho Yours implementation work, because python if treats 0 like False and any other value as True)
I’m trying to create a program that lists all the primes below an inputted number, and I came up with the code:
def primes():
num = 20
numlist = list(range(1,num+1))
i = len(numlist)
for j in numlist[2:]:
ans = divisible(j,i)
if ans:
numlist.remove(j)
print(numlist)
def divisible(m,n):
if m!=n and m%n==0:
return True
elif n == 1:
return False
else:
divisible(m, n-1)
primes()
(I used an in-browser IDE so the num part was a proxy for the input.)
My idea was to create a separate function divisible() that when inputted two ints, m and n, would check if n divides m. I'm not sure if I was right in my recursion, but I wrote divisible(m,n-1) the idea was that it would iterate through all the integers from n downward and it would return True if any n divided m, or False if it reached 1.
In the main code, m iterated through all the numbers in a list, and n is the total number of elements in the same list. I put the print(numlist) inside the if statement as an error check. The problem I’m having is nothing is printing. The code returned literally nothing. Is there something I’ve missed in how recursion works here?
There's a lot wrong here:
You've made a common beginner's recursion error in that you have a recursive function that returns a value, but when you call it recursively, you ignore the returned value. You need to deal with it or pass it along.
It seems like this modulus is backward:
if ... and m%n==0:
Maybe it should be:
if ... and n % m == 0:
You're code doesn't appear to be calculating primes. It's looks like it's calculating relative primes to n.
You start your list of numbers at 1:
numlist = list(range(1,num+1))
But you start testing at index 2:
for j in numlist[2:]:
Which is the number 3 and you never check the divisibility of the number 2.
Even with all these fixes, I don't feel your algorithm will work.
Your divisible function doesn't return anything if it falls into else part. change it as
def divisible(m, n):
if m!=m and m%n==0:
return True
elif n==1 :
return False
else:
return divisible(m,n-1)
This should work
I have tried this following code and it takes a lot of time when I set lower = 0 and upper = 10000
def sumPdivisors(n):
'''This function returns the sum of proper divisors of a number'''
lst = []
for i in range(1,n//2+1):
if n%i == 0:
lst.append(i)
return(sum(lst))
lower = int(input("Enter the lower value of range: "))
upper = int(input("Enter the upper value of range: "))
lst = []
for i in range(lower, upper+1):
if i == 0:
continue
else:
for j in range(i, upper):
if i!=j and sumPdivisors(i) == j and sumPdivisors(j) == i:
lst.append((i,j))
break
print(lst)
There are two things that you could do here.
Memoization
There's already a great explanation of what memoization is elsewhere on this site [link], but here's how it's relevant to your problem:
sumPdivisors is called very frequently in the for-loop at the bottom of your code snippet. For really large inputs n, it will take a long time to run.
sumPdivisors is called with the same input n multiple times.
You can speed things up by saving the result of calling sumPdivisors on different inputs somehow, like in a dictionary that maps integers to the resulting output when you call sumPdivisors with that corresponding integer. This is kind of what memoization is. You're precomputing the possible outputs of sumPdivisors and storing them for later. Read the link for a more in-depth explanation.
Don't add the numbers in sumPdivisors to a list
You can just add these numbers as you iterate instead of appending them to a list, then summing them. This change won't have as great of an impact as adding memoization to your code.
I am trying to make a simple loop where it prints the output numbers 0-9 on separate lines. What am I doing wrong? I have looked at the examples on here and they don't really help me. If you could explain where I went wrong that would be very helpful.
def singleline(item):
number = 0
while number < 10:
print(number)
number = number + 1
You've defined a function but you haven't called it. Just add
singleline(1)
to the end of the script.
Try using a for loop with range.
for num in range(10):
print(num)
This is more concise than using a while loop.
Also, if you are using a while loop, I would recommend using number+=1. It is the same as number=number+1, but just looks cleaner.
Firstly remember to call the function at the end of your otherwise you have just executed it singleline(). Also you haven't used the item you put into the parameters.
A better way to write this using a while loop would be.
def singleline():
num = 0
while num < 10:
print(num)
num += num
The += just means add one to of the variable on the left to the variable on the right. For example
a = 1
b = 2
a += b
a would not equal 3 because it adds b to it's original value.
However if you wanted something more efficient you could use this:
for num in range(10):
print(num)
for loops work in the same way as a while loop (take a condition and do content until stopped) but does it for the amount of times set. So in simple terms all this code means is print num plus 1.
Woah, your code is way too complicated -
for x in range (0, 10):
print x
Should work perfectly (python), Good Luck!
I want to know if is it possible to change the value of the iterator in its for-loop?
For example I want to write a program to calculate prime factor of a number in the below way :
def primeFactors(number):
for i in range(2,number+1):
if (number%i==0)
print(i,end=',')
number=number/i
i=i-1 #to check that factor again!
My question : Is it possible to change the last two line in a way that when I change i and number in the if block, their value change in the for loop!
Update: Defining the iterator as a global variable, could help me? Why?
Short answer (like Daniel Roseman's): No
Long answer: No, but this does what you want:
def redo_range(start, end):
while start < end:
start += 1
redo = (yield start)
if redo:
start -= 2
redone_5 = False
r = redo_range(2, 10)
for i in r:
print(i)
if i == 5 and not redone_5:
r.send(True)
redone_5 = True
Output:
3
4
5
5
6
7
8
9
10
As you can see, 5 gets repeated. It used a generator function which allows the last value of the index variable to be repeated. There are simpler methods (while loops, list of values to check, etc.) but this one matches you code the closest.
No.
Python's for loop is like other languages' foreach loops. Your i variable is not a counter, it is the value of each element in a list, in this case the list of numbers between 2 and number+1. Even if you changed the value, that would not change what was the next element in that list.
The standard way of dealing with this is to completely exhaust the divisions by i in the body of the for loop itself:
def primeFactors(number):
for i in range(2,number+1):
while number % i == 0:
print(i, end=',')
number /= i
It's slightly more efficient to do the division and remainder in one step:
def primeFactors(number):
for i in range(2, number+1):
while True:
q, r = divmod(number, i)
if r != 0:
break
print(i, end=',')
number = q
The only way to change the next value yielded is to somehow tell the iterable what the next value to yield should be. With a lot of standard iterables, this isn't possible. however, you can do it with a specially coded generator:
def crazy_iter(iterable):
iterable = iter(iterable)
for item in iterable:
sent = yield item
if sent is not None:
yield None # Return value of `iterable.send(...)`
yield sent
num = 10
iterable = crazy_iter(range(2, 11))
for i in iterable:
if not num%i:
print i
num /= i
if i > 2:
iterable.send(i-1)
I would definitely not argue that this is easier to read than the equivalent while loop, but it does demonstrate sending stuff to a generator which may gain your team points at your next local programming trivia night.
It is not possible the way you are doing it. The for loop variable can be changed inside each loop iteration, like this:
for a in range (1, 6):
print a
a = a + 1
print a
print
The resulting output is:
1
2
2
3
3
4
4
5
5
6
It does get modified inside each for loop iteration.
The reason for the behavior displayed by Python's for loop is that, at the beginning of each iteration, the for loop variable is assinged the next unused value from the specified iterator. Therefore, whatever changes you make to the for loop variable get effectively destroyed at the beginning of each iteration.
To achieve what I think you may be needing, you should probably use a while loop, providing your own counter variable, your own increment code and any special case modifications for it you may need inside your loop. Example:
a = 1
while a <= 5:
print a
if a == 3:
a = a + 1
a = a + 1
print a
print
The resulting output is:
1
2
2
3
3
5
5
6
Yes, we can only if we dont change the reference of the object that we are using. If we can edit the number by accessing the reference of number variable, then what you asked is possible.
A simple example:
a=[1,2,3]
a=a+[4]==>here, a new object is created which plots to different address.
a+=[4]==>here , the same object is getting updated which give us the desired result.
number=10
list1=list(range(2,number+1))
# list1
for i in list1:
print(list1,i)
if (number%i==0):
print(i,end=',')
number=number//i #we can simply replace it with number//=i to edit the number without changing the reference or without creating a new object.
try:
[list1.pop() for i in range(10,0,-1) if(i>number)]
#here pop() method is working on the same object which list created by number refers. so, we can able to change the iterable in the forloop.
except:
continue
i=i-1 #to check that factor again!