I have been programming in python for a little while now, and decided to teach my friend as well. I asked him to make a method that would return a list of all the factors of a number, he gave me a script that was a little inefficient but still looked like it should have worked to me. However when run the program freezes up both my and his computer (I have a top of the line gaming pc so I don't think it is using to many resources). I showed him how to fix it, however I still cannot pinpoint what is causing the problem. Here is the code, thanks for your time!
def factors(numb):
facs = []
for i in range(1,int(numb // 2)):
if numb % i == 0:
facs.append(i)
for i in facs:
facs.append((numb / i))
return facs.sort()
p.s. it never throws an error, even after having been let run for a while. Also it is in python 3.4
Your problem is here:
for i in facs:
facs.append((numb / i))
The for loop is iterating over every number in facs, and each time it does it adds a new number to the end. So each time it gets one place closer to the end of the list, the list gets one place longer. This makes an infinite loop and slowly swallows up all your memory.
EDIT: Solving the problem
The loop isn't actually necessary (and neither is the sorting, as the function produces an already sorted list)
def factors(numb):
facs = []
for i in range(1,int(numb // 2)):
if numb % i == 0:
facs.append(i)
return facs
Should work fine.
The problem is in this fragment:
for i in facs:
facs.append((numb / i))
You have a self-incrementing sequence here.
Try to analyse these lines(7,8), Here logic in not looking correct as you aspect(infinite loop).
for i in facs:
facs.append((numb / i))
otherwise test it.
def factors(numb):
l = [1,2,3,4]
for i in l:
print i
l.append(numb/i)
factors(10) // function call
Related
So here's my code.
def bubblesort(list):
global step
global oldlist
print("""
ORIGINAL LIST""")
print(list)
for i in range(len(list)):
for j in range(len(list)-1):
if float(list[j])>float(list[j+1]):
list[j], list[j+1] = list[j+1], list[j]
if oldlist==list:
**end(list)**
else:
oldlist=list
step=step+1
print("""
STEP""",step)
print(list)
end(list)
def end(list):
global step
step=step+1
print("""
STEP""",step)
print(list)
step=0
oldlist=[]
list=[]
number=int(input("How many numbers do you want to input to sort? : "))
for i in range(1,number+1):
value=float(input("INPUT NUMBER : "))
list.append(value)
bubblesort(list)
The issue is the bit of code which I have is "end(list)" bare in mind I've included the ** to make it easier to see on here it's not actually in the code. It simply won't call the subroutine when I ask it to. I know it definitely runs through the if since if i put a "print" or "break" in they both work it just won't jump to a sub-routine. Furthermore, the time I call that subroutine later on in the code works and does go to the subroutine. So i'm a bit lost as to what I've done wrong here. Any help? Would be much appreciated :)
There are quite a few things wrong with your code, and your question. Let's go through them:
First of all, the formatting was not great (I've suggested an edit). This might not sound like a big deal ("Hey, as long as it works...") but it's actually crucial: I work with python every day, and I had trouble understanding your code
You're talking about subroutines. In python, we usually refer to those as functions, or methods.
You're using globals variables all over the place. This might work in little toy examples like this one, but it will fall apart VERY fast
As David Buck said, list is one of the basic data structures: 1 in an instance of int and [1,2,3] is an instance of list). It's a really bad idea to override it.
I'm not sure what you're trying to do with the end() function. It seems do very little, and what it does is not related to its name...
You create an oldlist list but never really do anything with it. What is it supposed to to ?
With that in mind, here is my proposition:
def main():
# I like to put the main code in a "main" function, so that it can be at the top
# of the file. We'll call main() from the bottom of the file
# Make our program pretty, with a little branding
print("===== Number Sorter 9000 =====")
# 'numbers' is not the name of anything yet, so we can use it safely
numbers = []
# This will loop forever, unless we tell it to stop. It allows us to skip the
# part where you ask the user for a number of values: Simply enter the values
# one by one, and press enter once last time when done.
while True:
value = input(f"Number {len(numbers)+1} (leave empty to continue): ")
# Decide what to do with the value we received. If it's a number,
# add it to our list, if it's empty, stop collecting numbers
if value:
# Make sure the value is a number ()
value = float(value)
# Add the number to the list
numbers.append(value)
else:
# This will get us out of the number-asking loop
break
print("Number Sorter 9000 will now sort your numbers")
sorted_numbers = bubblesort(numbers)
print("Number Sorter 9000 has sorted your numbers:")
print(sorted_numbers)
def bubblesort(numbers):
# Here I've removed things that were not doing much.
# There are some ways to improve the algorithm itself, but I'll let you do that
for i in range(len(numbers)):
for j in range(0, len(numbers)-i-1):
if numbers[j] > numbers[j+1]:
numbers[j], numbers[j+1] = numbers[j+1], numbers[j]
# We 'return' the result from the function, so that code that calls the
# bubblesort() function can use the result
return numbers
# Lastly, we call the "main" function to get everything started. Without this
# line, nothing happens: We've just explained to the computer how to do some
# stuff, but we haven't asked it to *DO* anything
main()
Well, I hope this was not too much information. I've tried to keep things simple, but feel free to ask if something is not clear
I have tested the following python script on 2 Windows machines, and onlinegdb's python compiler.
On the Windows machines, this code when run as it is, just exits midway, non-deterministically, with no error message or warning. I tested with python 3.9.6.
It works as expected and does not crash when the function nCr is a different function outside isPrime. You can comment and uncomment the appropriate text.
On onlinegdb's python compiler, it works as expected in both cases.
import sys
sys.setrecursionlimit(10**6)
# def nCr(n, r):
# if r == 0:
# return 1
# else:
# return nCr(n, r-1) * (n-r+1) / r
def isPrime(N):
def nCr(n, r):
if r == 0:
return 1
else:
return nCr(n, r-1) * (n-r+1) / r
if nCr(N, N//2) % N == 0:
return True
else:
return False
for i in range(4050, 4060 + 1):
print(f"{i}: {isPrime(i)}")
else:
print("Done")
Any clues on what may be causing this? Is it possible to get this to run correctly on Windows? Or should I just avoid inner functions entirely?
Note: I know that the prime checker's logic is incorrect.
Note: You can try a larger range by changing the 4th last line if you are not able to reproduce the crash.
Edit 1:
We found that:
If the recursive depth is sufficiently large, it will most likely cause a crash on all platforms. This number, although large, would still be small enough such that only a small portion of the machines memory is being used.
Moving the function to module level does not prevent the crash.
Increasing system recursionlimit does not affect the crash, if it is more than the depth at which the crash occurs.
So, the question now is:
Is there a way to estimate the depth at which the crash will occur? Also, the depth at which the crash occurs is very small, and if we use our own stack instead of calling the function recursively, then we can keep going till the machine is out of memory. So, should we just avoid using recursive function calls in python?
Sorry for the vague title, but since I have no clue what the reason for my problem might be I don't know how to describe it better. Anyway, I have a strange problem in connection with multiprocessing and hope some of you can help me.
I'm currently dealing with convex optimization, especially with parallelizing the tasks. My goal is to utilize as many cores as possible on a multi-core-machine (on which I get access only temporarily).
Therefore, I took a look on the CVXPY's Tutorial page and tried to implement an easy example to get into the topic (scroll down, it's the last example on the page). I shortened the example to the parts which are necessary for my question, so my code looks as follows:
import cvxpy as cp
import numpy
from multiprocessing import Pool
# Assign a value to gamma and find the optimal x.
def get_x(gamma_value):
print("E")
gamma.value = gamma_value
result = prob.solve()
print("F")
return x.value
# Problem data.
n = 15
m = 10
numpy.random.seed(1)
A = numpy.random.randn(n, m)
b = numpy.random.randn(n)
# gamma must be nonnegative due to DCP rules.
gamma = cp.Parameter(nonneg=True)
# Construct the problem.
x = cp.Variable(m)
error = cp.sum_squares(A # x - b)
obj = cp.Minimize(error + gamma*cp.norm(x, 1))
prob = cp.Problem(obj)
# Construct a trade-off curve of ||Ax-b||^2 vs. ||x||_1
sq_penalty = []
l1_penalty = []
x_values = []
print("A")
gamma_vals = numpy.logspace(-4,6, num = 6400)
print("B")
for val in gamma_vals:
gamma.value = val
print("C")
# Parallel computation (set to 1 process here).
pool = Pool(processes = 1)
print("D")
x_values = pool.map(get_x, gamma_vals)
print(x_values[-1])
As you might have observed, I added some prints with capital letters, they served to find out where exactly the issue occurs, so I can refer to them in my problem description;
When I run the code the code processes and the letters "A" to "D" are displayed on the screen, so everything's fine until passing "D". But then the program kind of gets stuck. The CPU load is still high, so there definitely is going on something, but the code never reaches capital "E", which would be after successfully starting
x_values = pool.map(get_x, gamma_vals).
In my eyes it looks a bit like being stuck in an infinite loop.
Therefore, I guess someting with this pool.map function must be fishy. First, I thought that calling this function might be time-consuming and therefore it takes long to process (but that's rubbish, the optimization starts within the get_x function, so no reasoning).
Nevertheless, I tried to run my program on the multi-core-machine (with multiple cores, as well as with only a single core) and - surprise - it successfully passed this line nearly instantaneous and started with the actual optimization problem (and finally solved it).
So my issue is, that I don't know what's going wrong on my computer and how to fix it.
I can't access the machine at any time so - of course - I want to try the code on my computer first before uploading it, which isn't possible if even this easy toy-example doesn't work.
I' be grateful for any ideas/help!
Thank you in advance!
FOOTNOTE: I am using WIN10, the multi-core machine uses Linux
This code was written in Python 3. I am trying to find the 10001st prime number.
#10001st prime number
mylist=[]
def prime_index(n):
for i in range(99**99):
for x in range(2, int(i**1/2)):
if i % x == 0:
return False
return True
mylist.append(i)
n=int(n+1)
print(mylist[n])
break
prime_index(10001)
When I run, it says "list index out of range", referring to print(mylist[n]).
However I have been adding primes to the list along the way in the mylist.append(i). So can someone tell me what is the problem here because I do not understand what is going on. Is 99**99 too small? Or more subtle problem with code?
99**99 is not too small; if you actually print it, you're well beyond what you need (if you tried to run it out, you'd never finish, it's 657 bits of work). But your loop makes no sense; your inner loop will return either True or False immediately if it executes even once.
"Luckily" for you, it never executes even once. The first outer loop sets i to 0 the first time, so the inner loop doesn't run at all (side-note, you probably want i ** (1/2), not i ** 1 / 2; exponentiation has higher precedence than division). Because it doesn't run, you end up indexing into an empty list (and asking for index 10001 no less).
There are far too many problems in this code to address them all; look for other trial division prime finding code to get an idea of what it should look like.
The problem is that you try to print out the 10001st element as soon as you find (or not) the first prime. Also, note that you return from the routine without finding any prime number -- if you were to get that far. There is no way to reach the append statement.
You got to the print statement only because your first iteration has i = 0, so you don't enter the for loop at all.
Please follow the posting guidelines: take the time to research how to generate prime numbers. It can be much faster than you're doing, and will give you a nice, succinct bit of code to put into your program.
I am learning Python 3 and working on an exercise that calls for writing a Python program which simulates/reads a BASIC program as input. I am stuck on writing the part of the Python program that should detect infinite loops. Here is the code I have so far:
def execute(prog):
while True:
location = 0
if prog[location] == len(prog) - 1:
break
return "success"
getT = prog[location].split()
T = len(getT) - 1
location = findLine(prog, T)
visited = [False] * len(prog)
Here, prog is a list of strings containing the BASIC program (strings are in the form of 5 GOTO 30, 10 GOTO 20, etc.).
T is the target string indicated in prog[location].
If the BASIC program has an infinite loop, then my Python program will have an infinite loop. I know that if any line is visited twice, then it loops forever, and my program should return "infinite loop".
A hint given by the tutorial assistant says "initialize a list visited = [False] * len(prog) and change visited[i] to True when prog[i] is visited. Each time through the loop, one value updates in visited[]. Think about how you change a single value in a list. Then think about how you identify which value in visited[] needs to change."
So this is the part I am stuck on. How do I keep track of which strings in prog have been visited/looped through?
I'm not sure I agree that visiting a line twice proves an infinite loop. See the comments under the question. But I can answer the actual question.
Here's the hint:
A hint given by the tutorial assistant says "initialize a list visited = [False] * len(prog) and change visited[i] to True when prog[i] is visited. Each time through the loop, one value updates in visited[]. Think about how you change a single value in a list. Then think about how you identify which value in visited[] needs to change."
This is saying you should have two lists, one that contains the program, and one that contains true/false flags. The second one is to be named visited and initially contains False values.
The Python code is just like the hint says:
visited = [False] * len(prog)
This uses the * list operator, "list repetition", to repeat a length-1 list and make a new list of a longer length.
To change visited[i] to True is simple:
visited[i] = True
Then you can do something like this:
if visited[i]:
print("We have already visited line {}".format(i))
print("Infinite loop? Exiting.")
sys.exit(1)
Note that we are testing for the True value by simply saying if visited[i]:
We could also write if visited[i] == True: but the shorter form is sufficient and is customary in the Python community. This and other customary idioms are documented here: http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html
For a program this small, it's not too bad to keep two lists like this. For larger and complex programs, I prefer to keep everything together in one place. This would use a "class" which you might not have learned yet. Something like this:
class ProgramCode(object):
def __init__(self, statement):
self.code = statement
self.visited = False
prog = []
with open(input_basic_program_file, "rt") as f:
for line in f:
prog.append(ProgramCode(line))
Now instead of two lists, we have a single list where each item is a bit of BASIC code and a visited flag.
P.S. The above shows an explicit for loop that repeatedly uses .append() to add to a list. An experienced Python developer would likely use a "list comprehension" instead, but I wanted to make this as easy to follow as possible.
Here's the list comprehension. Don't worry if it looks weird now; your class will teach this to you eventually.
with open(input_basic_program_file, "rt") as f:
prog = [ProgramCode(line) for line in f]
I know of no automatic way of infinite loop detection in Python, but by using divide and conquer methods and testing individual functions, you can find the offending function or block of code and then proceed to debug further.
If the Python program outputs data, but you never see that output, that's a good indicator you have an infinite loop. You can test all your functions in the repl, and the function that does "not come back" [to the command prompt] is a likely suspect.
You can write output under a debug variable of some sort, to be shut off when everything works. This could be a member variable of a Python class to which your code would have to have access to at any time, or you could have a module-scoped variable like Debug=1 and use debug levels to print varying amounts of debug info, like 1 a little, 2 more, 3, even more, and 4 verbose.
As an example, if you printed the value of a loop counter in a suspected function, then eventually that loop counter would keep printing well beyond the count of data (test records) you were using to test.
Here is a combination I came up with using parts of J. Carlos P.'s answer with the hints that steveha gave and using the hint that the instructions gave:
def execute(prog):
location = 0
visited = [False] * len(prog)
while True:
if location==len(prog)-1:
return "success"
findT = prog[location].split()
T = findT[- 1]
if visited[location]:
return "infinite loop"
visited[location] = True
location = findLine(prog, T)