My Code for Perfect Number - python

So far, I've learned about for loops, if statements, and counting so it would be great to get feedback using only these topics. I was trying to solve the Perfect Number problem where the divisors excluding the number add up to that number. So for 6, The divisors 1,2,3 add up to 6. I've tried looking at other posts, but I wanted to know why my code specifically isn't working. I've tried solving the problem, and I feel that I'm almost there. I just have one issue. This is what I have so far:
#
num = 30
for i in range(1,num+1):
count = 0
for k in range(1,num+1):
if i%k == 0 and i!=k:
count += k
if count == i:
print(k,'Perfect',i)
#
The output on shell gives me this:
3 Perfect 6
8 Perfect 24
14 Perfect 28
#
I know that 24 is not a perfect number. The highest divisor for 24 excluding 24 should be 12, but I'm getting 8. This is why it's showing me that 24 is perfect. Can anyone clarify why I'm not able to get 12?

You have to count all divisors, before you make a conclusion, your code goes up to 8 for 24, then sums up all divisors so far and declares 24 a perfect number, not waiting for other divisors to appear.
Your code should looks like this:
for i in range(1,num+1):
count = 0
for k in range(1,i): # no point searching for numbers greater than i
if i%k == 0 :
count += k
if count == i:
print('Perfect',i)
and produce:
('Perfect', 6)
('Perfect', 28)

Your problem is that you're checking whether count == i in the wrong place. You need to check after the entire count summation is finished, not after each addition to the count sum.
num = 30
for i in range(1,num+1):
count = 0
for k in range(1,num+1):
if i%k == 0 and i != k:
count += k
if count == i:
print(k,'Perfect',i)
Also, if you want slightly more efficient code, you could do the subtraction afterwards instead of checking each value. Also, as lenik suggested, you only need to count to i (since i can't have any divisors larger than itself.) Even more efficiently, one could just use a Sieve of Eratosthenes-like approach, and count to sqrt(i)+1, finding the corresponding factors along the way:
from math import sqrt
num = 30
for i in range(1,num+1):
count = 0
for k in range(1,sqrt(i) + 1):
if i%k == 0:
count += k
factor = count/k
# The conditional is necessary in case i is a perfect square.
if k != factor:
count += factor
if count - i == i:
print(k,'Perfect',i)

12 is not perfect 1 + 2 + 3+ 4 + 6 != 12
second for also have problem in count (change it to i+1)
and critical problem was las check was in for
num = 30
for i in range(1,num+1):
count = 0
last = 0
for k in range(1,i):
if i%k == 0:
count += k
last = k
if count == i:
print(last,'Perfect',i)
result :
3 Perfect 6
14 Perfect 28

Related

A program that finds all four of the perfect numbers that are less than 10000

everyone.
I have a question about an exercise from Brian Heinold's A Practical Introduction to
Python Programming that reads "A number is called a perfect number if it is equal to the sum of all of its divisors, not including the number itself. For instance, 6 is a perfect number because the divisors of 6 are 1, 2, 3, 6 and 6 = 1 + 2 + 3. As another example, 28 is a perfect number because its divisors are 1, 2, 4, 7, 14, 28 and 28 = 1 + 2 + 4 + 7 + 14. However, 15 is not a perfect number because its divisors are 1, 3, 5, 15 and 15 ̸= 1 + 3 + 5. Write a program that finds all four of the perfect numbers."
I'm a beginner. I tried. My code doesn't work. Please tell me where did I go wrong and why does the program print the number 1 endlessly why I press Run.
Thank you.
# We have to check all numbers from 1 to 10000.
for i in range(1,10001):
# Since all numbers are divisible by 1,
#we can set 1 as the initial value.
sum_div = 1
#The potential divisors also range from 1 to 10000,
#therefore we can use this nested loop:
for j in range(1,20001):
# A j value can be a divisor if the remainder is zero.
# AND the range of the divisors must not include the number itself.
# Since 1 is already known to be a divisor, we can start checking from 2.
if i % j == 0 and j != i:
#We already have 1 as the first divisor,
#so now we have to add the other divisors.
sum_div = sum_div + j
#If the sum of the divisors equals the number,
#then we got the number we need.
if sum_div == i:
print(i)
The j for loop should be from 2 to i-1 not 1 to 20001 and your if logic should be outside j for loop indicating we are done with counting sum
# We have to check all numbers from 1 to 10000.
for i in range(1,10001):
# Since all numbers are divisible by 1,
# we can set 1 as the initial value.
sum_div = 1
# The potential divisors also range from 1 to 10000,
# therefore we can use this nested loop:
for j in range(2, i):
# A j value can be a divisor if the remainder is zero.
# AND the range of the divisors must not include the number itself.
# Since 1 is already known to be a divisor, we can start checking from 2.
if i % j == 0 and j != i:
# We already have 1 as the first divisor,
# so now we have to add the other divisors.
sum_div = sum_div + j
# If the sum of the divisors equals the number,
# then we got the number we need.
if sum_div == i:
print(i)
At first glance, the reason your code is printing 1 endlessly is because you're comparing sum_div and i within the loop that iterates through j. if sum_div == i needs to be an indentation level higher than it currently is.
Secondly, because you've already considered 1 as a divisor when initializing sum_div, you do not need to start j from 1. It can start from 2.
Divisors will always be less than the number you're checking for, so you do not need j to loop from 1 to 20001 - it's enough to check till the value of i.
The value of i can start from 2, because we're not interested in whether 1 is a perfect number or not.
Based on these observations, here's the modified snippet that works for me.
for i in range(2, 10001):
sum_div = 1
for j in range(2, i):
if i%j == 0 and j != i:
sum_div += j
if sum_div == i:
print(i)
print("End of program")
Hope this helps!

I am trying to find the Multiplicative Persistance of a number to number+1 in a loop. So what should i do to fix hte code?

def per(n,steps=0):
if len (str(n))==1:
print(n)
print "TOTAL STEPS" + str(steps)
return "DONE"
steps += 1
digits = [int(i)for i in str(n)]
result = 1
for j in digits:
result *= j
print(result)
per(result,steps)
count = 0
while True:
print count
count += 1
str(wantedresult) == 12
str(steps) >= 11
if str(steps) == str(wantedresult)
print str(n)
break
I am noob.
I have another encoded and working code in my pockets(metaphorically) but not in a loop
so i wanted my results like this example in my other code is this
if my number is 277777788888899 it has an output of this
4996238671872
438939648
4478976
338688
27648
2688
768
336
54
20
0
0
TOTAL STEPS11
ummm you might need this
my error in the first code is
File "source_file.py", line 21
if str(steps) == str(wantedresult)
^
SyntaxError: invalid syntax
I think what you're trying to accomplish is to find the smallest number with a persistance of wantedresult by brute forcing all the number one by one? If so, here's something that does not differ too much from your first version:
def per(n,steps=0,display=False):
# display the number at each iteration
if display:
print(n)
if len(str(n)) > 1:
steps += 1
digits = [int(i)for i in str(n)]
result = 1
for j in digits:
result *= j
steps = per(result,steps,display)
return steps
wantedresult = 6
persistance = 0
count = 0
while True:
count += 1
persistance = per(count)
if persistance == wantedresult:
print('The smallest number with a persistance of', wantedresult, 'is', count)
per(count,display=True) # display the iterations for this number
print('TOTAL STEPS', wantedresult)
break
However it is suitable only for small persistance number and it might take a while if you want to find 277777788888899 with this approach.
BTW the syntax error you got is because you forgot the colon after the if statement.
Hope it helped.

Part of this prime number program is just not making sense to me

Could someone explain
for k in range(2, 1+int(sqrt(i+1))):
to me? I am having a hard time comprehending how
1+int(sqrt(i+1)
truly works.
I understand 1 is being added to i, and it is being square rooted, and it must be an integer. But I don't comprehend how that achieves the goal of the whole program
from math import sqrt
count = 1
i = 1
while count < 1000:
i += 2
for k in range(2, 1+int(sqrt(i+1))):
if i%k == 0:
break
else:
# print(i) ,
count += 1
# if count%20==0: print ""
print i
whose goal is to find the 1000th prime.
If a number is to be tested for primality, it is sufficient to test all factors up to sqrt(number), because any factor above sqrt(number) has a corresponding factor below sqrt(number).
e.g. if you want to test if 36 is prime, it is sufficient to test up to 6 - for example, 12 is a factor of 36, but its other factor is 3, which you already tested by then.

How to generate the 1000th prime in python?

count = 0
i = 11
while count <= 1000 and i <= 10000:
if i%2 != 0:
if (i%3 == 0 or i%4 == 0 or i%5 == 0 or i%6 == 0 or i%7 == 0 or i%9 == 0):
continue
else:
print i,'is prime.'
count += 1
i+=1
I'm trying to generate the 1000th prime number only through the use of loops. I generate the primes correctly but the last prime i get is not the 1000th prime. How can i modify my code to do so. Thank in advance for the help.
EDIT: I understand how to do this problem now. But can someone please explain why the following code does not work ? This is the code I wrote before I posted the second one on here.
count = 1
i = 3
while count != 1000:
if i%2 != 0:
for k in range(2,i):
if i%k == 0:
print(i)
count += 1
break
i += 1
Let's see.
count = 1
i = 3
while count != 1000:
if i%2 != 0:
for k in range(2,i):
if i%k == 0: # 'i' is _not_ a prime!
print(i) # ??
count += 1 # ??
break
i += 1 # should be one space to the left,
# for proper indentation
If i%k==0, then i is not a prime. If we detect that it's not a prime, we should (a) not print it out, (b) not increment the counter of found primes and (c) we indeed should break out from the for loop - no need to test any more numbers.
Also, instead of testing i%2, we can just increment by 2, starting from 3 - they will all be odd then, by construction.
So, we now have
count = 1
i = 3
while count != 1000:
for k in range(2,i):
if i%k == 0:
break
else:
print(i)
count += 1
i += 2
The else after for gets executed if the for loop was not broken out of prematurely.
It works, but it works too hard, so is much slower than necessary. It tests a number by all the numbers below it, but it's enough to test it just up to its square root. Why? Because if a number n == p*q, with p and q between 1 and n, then at least one of p or q will be not greater than the square root of n: if they both were greater, their product would be greater than n.
So the improved code is:
from math import sqrt
count = 1
i = 1
while count < 1000:
i += 2
for k in range(2, 1+int(sqrt(i+1))):
if i%k == 0:
break
else:
# print(i) ,
count += 1
# if count%20==0: print ""
print i
Just try running it with range(2,i) (as in the previous code), and see how slow it gets. For 1000 primes it takes 1.16 secs, and for 2000 – 4.89 secs (3000 – 12.15 ses). But with the sqrt it takes just 0.21 secs to produce 3000 primes, 0.84 secs for 10,000 and 2.44 secs for 20,000 (orders of growth of ~ n2.1...2.2 vs. ~ n1.5).
The algorithm used above is known as trial division. There's one more improvement needed to make it an optimal trial division, i.e. testing by primes only. An example can be seen here, which runs about 3x faster, and at better empirical complexity of ~ n1.3.
Then there's the sieve of Eratosthenes, which is quite faster (for 20,000 primes, 12x faster than "improved code" above, and much faster yet after that: its empirical order of growth is ~ n1.1, for producing n primes, measured up to n = 1,000,000 primes):
from math import log
count = 1 ; i = 1 ; D = {}
n = 100000 # 20k:0.20s
m = int(n*(log(n)+log(log(n)))) # 100k:1.15s 200k:2.36s-7.8M
while count < n: # 400k:5.26s-8.7M
i += 2 # 800k:11.21-7.8M
if i not in D: # 1mln:13.20-7.8M (n^1.1)
count += 1
k = i*i
if k > m: break # break, when all is already marked
while k <= m:
D[k] = 0
k += 2*i
while count < n:
i += 2
if i not in D: count += 1
if i >= m: print "invalid: top value estimate too small",i,m ; error
print i,m
The truly unbounded, incremental, "sliding" sieve of Eratosthenes is about 1.5x faster yet, in this range as tested here.
A couple of problems are obvious. First, since you're starting at 11, you've already skipped over the first 5 primes, so count should start at 5.
More importantly, your prime detection algorithm just isn't going to work. You have to keep track of all the primes smaller than i for this kind of simplistic "sieve of Eratosthanes"-like prime detection. For example, your algorithm will think 11 * 13 = 143 is prime, but obviously it isn't.
PGsimple1 here is a correct implementatioin of what the prime detection you're trying to do here, but the other algorithms there are much faster.
Are you sure you are checking for primes correctly? A typical solution is to have a separate "isPrime" function you know that works.
def isPrime(num):
i = 0
for factor in xrange(2, num):
if num%factor == 0:
return False
return True
(There are ways to make the above function more effective, such as only checking odds, and only numbers below the square root, etc.)
Then, to find the n'th prime, count all the primes until you have found it:
def nthPrime(n):
found = 0
guess = 1
while found < n:
guess = guess + 1
if isPrime(guess):
found = found + 1
return guess
your logic is not so correct.
while :
if i%2 != 0:
if (i%3 == 0 or i%4 == 0 or i%5 == 0 or i%6 == 0 or i%7 == 0 or i%9 == 0):
this cannot judge if a number is prime or not .
i think you should check if all numbers below sqrt(i) divide i .
Here's a is_prime function I ran across somewhere, probably on SO.
def is_prime(n):
return all((n%j > 0) for j in xrange(2, n))
primes = []
n = 1
while len(primes) <= 1000:
if is_prime(n):
primes.append(n)
n += 1
Or if you want it all in the loop, just use the return of the is_prime function.
primes = []
n = 1
while len(primes) <= 1000:
if all((n%j > 0) for j in xrange(2, n)):
primes.append(n)
n += 1
This is probably faster: try to devide the num from 2 to sqrt(num)+1 instead of range(2,num).
from math import sqrt
i = 2
count = 1
while True:
i += 1
prime = True
div = 2
limit = sqrt(i) + 1
while div < limit:
if not (i % div):
prime = False
break
else:
div += 1
if prime:
count += 1
if count == 1000:
print "The 1000th prime number is %s" %i
break
Try this:
def isprime(num):
count = num//2 + 1
while count > 1:
if num %count == 0:
return False
count -= 1
else:
return True
num = 0
count = 0
while count < 1000:
num += 1
if isprime(num):
count += 1
if count == 1000:
prime = num
Problems with your code:
No need to check if i <= 10000.
You are doing this
if i%2 != 0:
if (i%3 == 0 or i%4 == 0 or i%5 == 0 or i%6 == 0 or i%7 == 0 or i%9 == 0):
Here, you are not checking if the number is divisible by a prime number greater than 7.
Thus your result: most probably divisible by 11
Because of 2. your algorithm says 17 * 13 * 11 is a prime(which it is not)
How about this:
#!/usr/bin/python
from math import sqrt
def is_prime(n):
if n == 2:
return True
if (n < 2) or (n % 2 == 0):
return False
return all(n % i for i in xrange(3, int(sqrt(n)) + 1, 2))
def which_prime(N):
n = 2
p = 1
while True:
x = is_prime(n)
if x:
if p == N:
return n
else:
p += 1
n += 1
print which_prime(1000)
n=2 ## the first prime no.
prime=1 ## we already know 2 is the first prime no.
while prime!=1000: ## to get 1000th prime no.
n+=1 ## increase number by 1
pon=1 ## sets prime_or_not(pon) counter to 1
for i in range(2,n): ## i varies from 2 to n-1
if (n%i)==0: ## if n is divisible by i, n is not prime
pon+=1 ## increases prime_or_not counter if n is not prime
if pon==1: ## checks if n is prime or not at the end of for loop
prime+=1 ## if n is prime, increase prime counter by 1
print n ## prints the thousandth prime no.
Here is yet another submission:
ans = 0;
primeCounter = 0;
while primeCounter < 1000:
ans += 1;
if ans % 2 != 0:
# we have an odd number
# start testing for prime
divisor = 2;
isPrime = True;
while divisor < ans:
if ans % divisor == 0:
isPrime = False;
break;
divisor += 1;
if isPrime:
print str(ans) + ' is the ' + str(primeCounter) + ' prime';
primeCounter += 1;
print 'the 1000th prime is ' + str(ans);
Here's a method using only if & while loops. This will print out only the 1000th prime number. It skips 2. I did this as problem set 1 for MIT's OCW 6.00 course & therefore only includes commands taught up to the second lecture.
prime_counter = 0
number = 3
while(prime_counter < 999):
divisor = 2
divcounter = 0
while(divisor < number):
if(number%divisor == 0):
divcounter = 1
divisor += 1
if(divcounter == 0):
prime_counter+=1
if(prime_counter == 999):
print '1000th prime number: ', number
number+=2
I just wrote this one. It will ask you how many prime number user wants to see, in this case it will be 1000. Feel free to use it :).
# p is the sequence number of prime series
# n is the sequence of natural numbers to be tested if prime or not
# i is the sequence of natural numbers which will be used to devide n for testing
# L is the sequence limit of prime series user wants to see
p=2;n=3
L=int(input('Enter the how many prime numbers you want to see: '))
print ('# 1 prime is 2')
while(p<=L):
i=2
while i<n:
if n%i==0:break
i+=1
else:print('#',p,' prime is',n); p+=1
n+=1 #Line X
#when it breaks it doesn't execute the else and goes to the line 'X'
This will be the optimized code with less number of executions, it can calculate and display 10000 prime numbers within a second.
it will display all the prime numbers, if want only nth prime number, just set while condition and print the prime number after you come out of the loop. if you want to check a number is prime or not just assign number to n, and remove while loop..
it uses the prime number property that
* if a number is not divisible by the numbers which are less than its square root then it is prime number.
* instead of checking till the end(Means 1000 iteration to figure out 1000 is prime or not) we can end the loop within 35 iterations,
* break the loop if it is divided by any number at the beginning(if it is even loop will break on first iteration, if it is divisible by 3 then 2 iteration) so we iterate till the end only for the prime numbers
remember one thing you can still optimize the iterations by using the property *if a number is not divisible with the prime numbers less than that then it is prime number but the code will be too large, we have to keep track of the calculated prime numbers, also it is difficult to find a particular number is a prime or not, so this will be the Best logic or code
import math
number=1
count = 0
while(count<10000):
isprime=1
number+=1
for j in range(2,int(math.sqrt(number))+1):
if(number%j==0):
isprime=0
break
if(isprime==1):
print(number,end=" ")
count+=1

euler challenge 12, why does this python code fail?

The Following code keeps telling me a wrong number and I can't see why, know it's brute force but it should still work... also the number it returns has indeed over 500 divisors, 512 to be exact, help would be much appreciated
Number = 1
Count = 2
Found = False
while Found == False:
Divisors = 0
if (Number % 2) != 0:
for i in range(1, int(Number**(1/2)), 2):
if Number % i == 0:
Divisors += 1
else:
for i in range(1, int(Number**(1/2))):
if Number % i == 0:
Divisors += 1
if Divisors >= 500:
print (Number)
Found = True
else:
Number += Count
Count += 1
For reference: Problem 12 from the Euler Challange
The number of divisors of an integer is just the product of (1 + exponent) for each pure power in the factor decomposition of an integer.
As an example: 28 = 2^2 * 7
The powers are 2 and 1, so the number of divisors is (2+1)*(1+1) = 3*2 = 6. Easy one
Bigger one: 2047 * 2048 / 2 = 2^10 * 23 * 89
The powers are 10, 1 and 1, so the number of divisors is 11*2*2 = 44
Easier: 100 = 2^2 * 5^2
The powers are 2, 2 so there are 3*3=9 divisors. The same applies to 36=2^2*3^2. The only interesting part is the exponents.
So, use any prime factor decomposition (use a sieve, you don't need a primality test) it would be much faster and more reliable than trying each of the possible numbers.
def factorize(i):
# returns an array of prime factors
whatever
def number_of_divisors(i):
n = 1
for v in Counter(factorize(i)).values():
n *= v + 1
return n
I'm not sure what Euler Challenge 12 is, but one obvious issue is the (1/2). If you try typing that in a Python prompt, you'll get 0. The reason why is that it will try to do integer math. I suggest just putting (0.5), or alternatively you could do (1/2.0).
Your divisor counting method is wrong. 12 has 6 divisors, but your code only counts 2.
Problems:
a number often has divisors larger than its square root
range doesn't include its upper bound, so you're stopping too early
the code you have been write is searching till number**0.5 and it is wrong you must search until number/2
so the corrected answer is like below:
Note : I add some extra code to show the progress. and they are not affect the solution.
Another Note: since the Nubmer itself is not counted like in the problem example, I add once to perform that.
Number = 1
Count = 2
Found = False
big_Devisor = 0
print "Number Count Divisors"
while Found == False:
Divisors = 1 # because the Number is itself Devisor
if (Number % 2) != 0:
for i in range(1, int(Number/2), 2):
if Number % i == 0:
Divisors += 1
else:
for i in range(1, int(Number/2)):
if Number % i == 0:
Divisors += 1
if Divisors >= 500:
print (Number)
Found = True
else:
if Divisors > big_Devisor:
big_Devisor = Divisors
print Number,'\t', Count, '\t', Divisors
Number += Count
Count += 1

Categories