Output going beyond specified maximum in range() function - python

I am trying to answer the following practice question:
"Write a loop (we suggest a for loop) that prints the numbers from minimum to maximum, including minimum and maximum themselves. If even is True, print only the even numbers. If even is False, print only the odd numbers. You may assume minimum will always be less than maximum."
For this I have written the following code, and it works for certain minimum and maximum values:
minimum = 5
maximum = 14
even = True
if even:
for numbers in range(minimum, maximum+1, 2):
if numbers%2 == 0:
print(numbers)
elif numbers%2 == 1:
numbers += 1
print(numbers)
else:
for numbers in range(minimum, maximum+1, 2):
if numbers%2 == 1:
print(numbers)
elif numbers%2 == 0:
numbers += 1
print(numbers)
This generated my desired output of 6, 8, 10, 12, 14.
However, once my minimum, maximum and even values are altered, to below for example:
minimum = 29
maximum = 33
even = True
The code somehow generates an output of 30, 32 and 34. 34 > 33 and therefore it shouldn't be there, yet it is. I was under the assumption that range() works such that it doesn't include the maximum number and thus I used maximum+1 to include maximum as the question asked, yet it included a number that is even beyond maximum+1!
To test further, I tried altering the variables as following and discovered something as interesting as it is puzzling too:
minimum = 1
maximum = 4
even = False
As expected, I got 1, 3 as my output. However, when I changed minimum = 2, I got 3, 5 as my output instead!
Could someone please explain to me why the code is acting this way? Thanks in advance!

Because when you are in the for loop you are incrementing number variable, wich is the loop index, and should be managed by the loop itself.
Specifically when number is 33 when you reach
elif numbers%2 == 1:
numbers += 1
print(numbers)
it gets incremented by 1 and being 34 even it gets printed.
May I suggest an implementation:
for number in range(minimum, maximum+1):
if (number%2 == 0 and even):
print number
elif (number%2 != 0 and not even):
print number

When maximum is 33 and you make a range object that goes to maximum+1, the largest value you're going to see from it is maximum, which is 33. However, when you add 1 to that value with numbers += 1, you change that to 34, which is where you get 34. You can clean up your code by changing minimum and maximum as necessary before you start, rather than shifting every number in the range.
def printer(low, hi, even):
for num in range(low + (even == low%2), hi+1, 2):
print(num)

mn, mx, even = 5, 14, True
for x in range(mn + int(bool(mn % 2) == even), mx + 1, 2):
print(x)
int() converts a bool value inside to either 0 or 1, which is the necessary offset for starting.
PS To understand why you ran out of range in your code, assume numbers = 33, plug it in your code, and see what happens:
if numbers%2 == 0:
print(numbers)
elif numbers%2 == 1:
numbers += 1
print(numbers)

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!

Code is in Infinite Loop and I don't know Why

My code is stuck in an infinite loop on the following lines:
while i <= len(mylist):
if mylist[i][j] == number:
I've stepped through the code but still do not know how to fix it. The problem I'm trying to solve is as follows:
Define a procedure, check_sudoku,
that takes as input a square list
of lists representing an n x n
sudoku puzzle solution and returns the boolean
True if the input is a valid
sudoku square and returns the boolean False
otherwise.
A valid sudoku square satisfies these
two properties:
Each column of the square contains
each of the whole numbers from 1 to n exactly once.
Each row of the square contains each
of the whole numbers from 1 to n exactly once.
You may assume that the input is square and contains at
least one row and column.
The below code I've written should check for just the row, not the column. Any advice on how to fix it and what I've done wrong would be greatly appreciate, so I'll understand and not make the mistake again.
def check_sudoku(mylist):
i = 0
j = 0
number = len(mylist)
while i <= len(mylist):
if mylist[i][j] == number:
number = number - 1
j = 0
if number == 0:
i = i + 1
number = len(mylist)
else:
j = j + 1
if number not in list:
break
return False
return True
check_sudoku([[1, 2, 3, 4],
[1, 3, 1, 4],
[3, 1, 2, 3],
[4, 4, 4, 4]])
I'm going to explain the function with the list you supplied as an example.
What's happening is:
number = len(mylist)
number = 4
while 0 <= 4
if 1 == 4: // This condition will never be true and therefore doesn't run the code below it
The while will run again and the same will happen.
If you put this line
print("i: " + str(i) + " j: " + str(j))
Just under where the While Loop starts, you realise that i and j never increment and it stays on the first spot.
You have to increment i and j after your bigger if statement

Finding all numbers that evenly divide a number

So I'm trying to make a program that when I input a number it will give me all the factors(12->1,2,3,4,6,12). I only started programming very recently so there may be some very obvious things. But here's my code
numbers = [1]
newnum = 1
chosen = int(input("Enter what you want the factors of: "))
def factors(numbers,newnum,chosen):
lastnum = numbers[-1]
if (chosen == lastnum):
for number in numbers:
if (number % 1 != 0):
numbers.remove(number)
print (numbers)
else:
factors(numbers,newnum,chosen)
else:
newnum = numbers[-1] + 1
numbers.append(newnum)
print (numbers)
factors(numbers,newnum,chosen)
factors(numbers,newnum,chosen)
Ok, so I don't really need the redundancies addressed but if you see something that would completely stop the program from working please point it out. Sorry I bothered you all with this but I don't know what else to do.
There are lots of problems:
Every integer number modulo 1 is zero because each integer is divisible by one without remainder.
You remove items from the list you're iterating over, that will definetly give wrong results if you don't do it carefully!
You try to do recursion but you don't return the result of the recursive call. That's possible because you operate on a mutable list but it's generally not really good style
You don't have any inline comments explaining what that line is supposed to do, so it's hard to give any reasonable guidance on how to improve the code.
If you want a code that finds all factors, consider something like this:
chosen = int(input("Enter what you want the factors of: "))
def factors(chosen, currentnum=None, numbers=None):
# Recursion start, always append 1 and start with 2
if numbers is None:
numbers = [1]
currentnum = 2
# We're at the last value, it's always divisible by itself so
# append it and return
if currentnum == chosen:
numbers.append(currentnum)
return numbers
else:
# Check if the chosen item is divisible by the current number
if chosen % currentnum == 0:
numbers.append(currentnum)
# Always continue with the next number:
currentnum += 1
return factors(chosen, currentnum, numbers)
>>> factors(chosen)
Enter what you want the factors of: 12
[1, 2, 3, 4, 6, 12]
That's not the optimal solution but it uses recursion and gives a proper result. Just don't enter negative values or catch that case in the function at the beginning!
# Two Pointer Approach
ans = []
def divisor(val):
result = []
for i in range(1, val + 1):
ans.append(i)
i = 0
j = len(ans) - 1
while i < j:
if ans[i] * ans[j] == ans[-1]:
result.append(ans[i])
result.append(ans[j])
i += 1
else:
j -= 1
return sorted(result)
print(divisor(12))
# Output
>>> [1, 2, 3, 4, 6, 12]

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.

Calculating prime numbers

I am now doing the MIT opencourse thing, and already the second assignment, I feel it has left me out in the cold. http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00-introduction-to-computer-science-and-programming-fall-2008/assignments/pset1a.pdf
The specifics of it, are to write something that can calculate the 1000th prime number. We only know about the print, ==, =, 1=,if, else, elif, while, %, -,+,*,/, commands I think. We also don't yet know about importing libraries.
My Idea of how it would work is to take an odd number and try to divide it by, 3,4,5,6,7,8,9 and if %n !=0, then add a number to NumberofPrimes variable starting with 11 as the base of the tests, and assigning it a base value of 4 at the base of NumberofPrimes, though I don't know if that is even right, because I wouldn't know how to display the 1000th prime number.
Am I close?
The latest incarnation of it is as follows:
##calculate the 1000th prime number
potprime = 3
numberofprime = 1
cycle = if potprime%3 = 0:
break
if potpimre%4 = 0:
break
if potprime%5 = 0:
break
if potprime%6 = 0:
break
if potprime%7 = 0:
break
if potprime%8 = 0:
break
if potprime%9 = 0:
break
numberofprime + 1
potprime + 1
if potprime%2 == 0:
potprime = potprime + 1
if potprime != 0:
cycle
Where exactly am I going wrong? Walk me through it step by step. I really want to learn it, though I feel like I am just being left out in the cold here.
At this point, it would be more beneficial for me to see how a proper one could be done rather than doing this. I have been working for 3 hours and have gotten nowhere with it. If anybody has a solution, I would be more than happy to look at it and try to learn from that.
Looks like I am late
It is quite straight forward that if a number is not divisible by any prime number, then that number is itself a prime number. You can use this fact to minimize number of divisions.
For that you need to maintain a list of prime numbers. And for each number only try to divide with prime numbers already in the list. To optimize further it you can discard all prime numbers more than square root of the number to be tested. You will need to import sqrt() function for that.
For example, if you test on 1001, try to test with 3, 5, 7, 11, 13, 17, 19, 23, 29 and 31. That should be enough. Also never try to find out if an even number is prime. So basically if you test an odd number n, then after that test next number: (n + 2)
Have tested the below code. The 1000th prime number is 7919. Not a big number!!
Code may be like:
from math import sqrt
primeList = [2]
num = 3
isPrime = 1
while len(primeList) < 1000:
sqrtNum = sqrt(num)
# test by dividing with only prime numbers
for primeNumber in primeList:
# skip testing with prime numbers greater than square root of number
if num % primeNumber == 0:
isPrime = 0
break
if primeNumber > sqrtNum:
break
if isPrime == 1:
primeList.append(num)
else:
isPrime = 1
#skip even numbers
num += 2
# print 1000th prime number
print primeList[999]
The following code is gross, but since 1000 is indeed a small index, it solves your problem in a fraction of a second (and it uses only the primitives you are supposed to know so far):
primesFound = 0
number = 1
while primesFound < 1000:
number = number + 1 # start from 2
# test for primality
divisor = 2
numberIsPrime = True
while divisor*divisor <= number: # while divisor <= sqrt(number)
if number % divisor == 0:
numberIsPrime = False
break
divisor = divisor + 1
# found one?
if numberIsPrime:
primesFound = primesFound + 1
print number
You can test the solution here.
Now you should find a more efficient solution, optimize and maybe go for the 1000000-th prime...
For one thing, I'm pretty sure that in Python, if you want to have an if statement that tests whether or not A = B, you need to use the == operator, rather then the =.
For another thing, your algorithm would consider the number 143 to be prime, even though 143 = 11 * 13
You need keep track of all the prime numbers that you have already computed - add them to an array. Use that array to determine whether or not a new number that you are testing is prime.
It seems to me that you are jumping into the deep-end after deciding the kiddy-pool is too deep. The prime number project will be assignment 2 or 3 in most beginning programming classes, just after basic syntax is covered. Rather than help you with the algorithm (there are many good ones out there) I'm going to suggest that you attempt to learn syntax with the python shell before you write long programs, since debugging a line is easier than debugging an entire program. Here is what you wrote in a way that will actually run:
count = 4
n = 10 #I'm starting you at 10 because your method
#says that 2, 3, 5, and 7 are not prime
d = [2, 3, 4, 5, 6, 7, 8, 9] #a list containing the ints you were dividing by
def cycle(n): #This is how you define a function
for i in d: #i will be each value in the list d
if not n%i: #this is equal to if n%i == 0
return 0 #not prime (well, according to this anyway)
return 1 #prime
while count < 1000:
count += cycle(n) #adds the return from cycle to count
n += 1
print n - 1
The answer is still incorrect because that is not how to test for a prime. But knowing a little syntax would at least get you that wrong answer, which is better than a lot of tracebacks.
(Also, I realize lists, for loops, and functions were not in the list of things you say you know.)
Your code for this answer can be condensed merely to this:
prime_count = 1
start_number = 2
number_to_check = 2
while prime_count <= 1000:
result = number_to_check % start_number
if result > 0:
start_number +=1
elif result == 0:
if start_number == number_to_check:
print (number_to_check)
number_to_check +=1
prime_count +=1
start_number =2
else:
number_to_check +=1
start_number = 2
To answer your subsequent question, 'How do I keep track of all the prime numbers?
One way of doing this is to make a list.
primeList = [] # initializes a list
Then, each time you test a number for whether it is prime or not, add that number to primeList
You can do this by using the 'append' function.
primeList.append( potprime ) # adds each prime number to that list
Then you will see the list filling up with numbers so after the first three primes it looks like this:
>>> primeList
[11, 13, 17]
Your math is failing you. A prime number is a number that has 2 divisors: 1 and itself. You are not testing the numbers for primality.
I am very late on this but maybe my answer will be of use to someone. I am doing the same open course at MIT and this is the solution I came up with. It returns the correct 1000th prime and the correct 100,000th prime and various others in between that I have tested. I think this is a correct solution (not the most efficient I am sure but a working solution I think).
#Initialise some variables
candidate = 1
prime_counter = 1
while prime_counter < 1000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
print "The 1000th prime is: " + str(candidate)
While I was at it I went on and did the second part of the assignment. The question is posed as follows:
"There is a cute result from number theory that states that for sufficiently large n the product of the primes less than n is less than or equal to e^n and that as n grows, this becomes a tight bound (that is, the ratio of the product of the primes to e^n gets close to 1 as n grows).
Computing a product of a large number of prime numbers can result in a very large number,
which can potentially cause problems with our computation. (We will be talking about how
computers deal with numbers a bit later in the term.) So we can convert the product of a set of primes into a sum of the logarithms of the primes by applying logarithms to both parts of this conjecture. In this case, the conjecture above reduces to the claim that the sum of the
logarithms of all the primes less than n is less than n, and that as n grows, the ratio of this sum to n gets close to 1."
Here is my solution. I print the result for every 1,000th prime up to the 10,000th prime.
from math import *
#Initialise some variables
candidate = 1
prime_counter = 1
sum_logs = log(2)
while prime_counter < 10000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
# If the number is prime add its log to the sum of logs.
sum_logs = sum_logs + log(candidate)
if prime_counter%1000 == 0:
# For every 1000th prime print the result.
print sum_logs," ",candidate," ",sum_logs/candidate
print "The 10000th prime is: " + str(candidate)
Cheers,
Adrian
I came up with this solution in my interview, but I didn't get the job :( It has about 1/100 less iterations than the solution above:
from math import *
MAX_IDX=1000
MAX_IDX-=1
num_iter=0
l_pirme_list=[3]
candidate=l_pirme_list[0]
prime_counter=1
while prime_counter < MAX_IDX:
candidate+=2
#Cut the binary number in half. This is quite faster than sqrt()
bin_candidate=format(candidate, "2b")
max_prime_search=int(bin_candidate[:len(bin_candidate)/2+1],2)+1
# max_prime_search=sqrt(candidate)+1
candidate_is_prime=1
for prime_item in l_pirme_list:
num_iter+=1
if candidate % prime_item==0:
candidate_is_prime=0
break
elif prime_item > max_prime_search:
candidate_is_prime=1
break
if candidate_is_prime:
prime_counter+=1
l_pirme_list.append(candidate)
l_pirme_list.insert(0,2)
print "number iterations=", num_iter
print l_pirme_list[MAX_IDX]

Categories