Help - Infinite blank input lines?

I’m relatively new to Python. I’m trying to make a Quadratic Equation calculator, including negative number square roots (using cmath), and to do that I’ve made a few functions to get my answers and make them the way I want them to be. Everything was working pretty well but for some reason when I activated the code I got the value inputs correctly, but then infinite blank input lines. I figured out this happened when the return function of the remove_undesirables function I made was being executed. Why is this happening?

Code:



def quadratic_solver(a, b, c):
    from cmath import sqrt
    a = float(a)
    b = float(b)
    c = float(c)
    answer1 = (b + sqrt(b ** 2 - (4 * a * c))) / (2 * a)
    answer2 = (b - sqrt(b ** 2 - (4 * a * c))) / (2 * a)
    return [f"{answer1}", f"{answer2}"]


a_value = input("a value: ")
b_value = input("b value: ")
c_value = input("c value: ")

answers = quadratic_solver(a_value, b_value, c_value)


def is_real(number):
    for type_n in number:
        type_complex = complex(type_n)
        if type_complex - type_complex.real == 0j:
            return True
        else:
            return False


remove_in_real = ["(", ")", "+0j"]
remove_in_complex_or_imaginary = ["(", ")", "j"]


def remove_undesirables(remove_in, condition, undesirables_condition, undesirables_else):
    for type_n in remove_in:
        if condition:
            for item in undesirables_condition:
                type_new = str(type_n).replace(item, "")
        else:
            for item in undesirables_else:
                type_new = str(type_n).replace(item, "")
                type_new.split("+")
        remove_in_new = remove_in.append(type_new)
    return remove_in_new



done = remove_undesirables(answers, is_real(answers), remove_in_real, remove_in_complex_or_imaginary)

I’ve attached a picture of the blank input lines.

(I don’t know if it has anything to do with anything, sometimes when I activate the program there are some errors for a split second and then they disappear and it works.)

My feeling is that you need to be looking at this function:

def remove_undesirables(remove_in, condition, undesirables_condition, undesirables_else):
    for type_n in remove_in:
        if condition:
            for item in undesirables_condition:
                type_new = str(type_n).replace(item, "")
        else:
            for item in undesirables_else:
                type_new = str(type_n).replace(item, "")
                type_new.split("+")
        remove_in_new = remove_in.append(type_new)
    return remove_in_new

remove_in_new will always be None, that is to say it will never have a value, because remove_in_new = remove_in.append(type_new) will always return a None value. Unless you’re relying on that (which you may be) then having that line of code as simply remove_in.append(type_new) will not change the way that the function works.

Also, remove_in is an ever growing list in the for: loop.

I may be wrong, because this is quite a complicated script, but as is, I can’t see an exit point for the remove_undesirables function.


To add: if you code this in, then you’ll maybe better see my point:

...
for type_n in remove_in:
        print(
            f"remove_in len: {len(remove_in)}\ntype_n: {type_n}\nlast item in the list:{remove_in[-1]}")
        input("Enter to continue")
        print()
        if condition:
        ...

First, an important aside - it’s necessary to understand how communicating with a program works in the terminal.

You don’t have “input lines” - rather, your program is not what allows the user to type input. That happens in a separate program, the terminal window. This collects what you type and makes it available to Python a line at a time; and the input() function waits for input if there is none available yet (if there is a full line that has been typed, it will use that immediately) and returns it (so that you can, for example, use = to give that line of text a name).

Normally, you don’t notice this process, because things happen so fast in a computer program that you cannot type a whole line of text in between the steps - it will seem to just do whatever, and then wait for that incredibly slow human on the other side of the “standard input” to actually type something and press the Enter key already :wink:

But in your case, the program is stuck in an infinite loop, so it cannot progress to the next step after the remove_undesirables function (i.e., the end of the program, since you are just naming that result as done and not doing anything with it, such as printing it). During that time, you can type what you want, and the terminal (not your program) “echoes” what you type back to you (newlines and all).


So, the problem is to understand the infinite loop. Let’s look at the loop, and see why it becomes infinite:

for type_n in remove_in:
        if condition:
            for item in undesirables_condition:
                type_new = str(type_n).replace(item, "")
        else:
            for item in undesirables_else:
                type_new = str(type_n).replace(item, "")
                type_new.split("+")
        remove_in_new = remove_in.append(type_new)

Every time through the loop, Python will move to the next position in the remove_in list, and set type_n to name that next value.
But every time through the loop, another element will be added to the end of remove_in, because of remove_in.append(type_new). The loop will try to loop over these as well, and it will never run out - because it gets a new element for each one it handles.

I assume that what you meant was to build a new list that contains only the type_new results from each time through the loop. The new list is remove_in_new, so that is where we should append the values: remove_in_new.append(type_new). Notice that this does not use = anywhere. It should not, because of how .append works. Please see these references on Stack Overflow:

Fully general:

Particular to list methods (although there isn’t really anything special to say about them):


However, aside from that, there are still many things wrong with the logic. There are a lot of improvements that could be suggested, but I just want to focus on one thing that is definitely not the logic you want:

type_new = str(type_n).replace(item, "")
type_new.split("+")

This will not do what you want, because str(type_n) means the same string every time as you .replace each item. Unlike .append on a list, .replace on a string creates a new string and does not change the original string object (there are no methods for changing a string in-place). Similarly. .split on a string will not change the string, and writing something like type_new.split("+") just creates a list of all the split parts and then immediately throws that list away.

Reference:

1 Like

Here is a separate advice: Instead of computing both roots with the quadratic formula, compute one root using the quadratic formula and the other with the citardauc formula according to the sign of b.

See here, equations 7 and 8.

This might work better for you

# Import necessary modules
from cmath import sqrt

# Function to solve the quadratic equation
def quadratic_solver(a, b, c):
    # Convert input values to float
    a, b, c = float(a), float(b), float(c)
    
    # Calculate the solutions of the quadratic equation
    answer1 = (b + sqrt(b ** 2 - (4 * a * c))) / (2 * a)
    answer2 = (b - sqrt(b ** 2 - (4 * a * c))) / (2 * a)
    
    return [answer1, answer2]

# Function to format the solution
def format_solution(solution):
    # Check if the solution has an imaginary part
    if solution.imag == 0:
        return f"{solution.real}"
    else:
        # Format the real part if it's not zero
        real_part = f"{solution.real}" if solution.real != 0 else ""
        
        # Format the imaginary part, removing the '+' sign if it's 1
        imaginary_part = f"{solution.imag:+}j" if solution.imag != 1 else "j"
        
        return f"{real_part}{imaginary_part}"

# Get input values from the user
a_value = input("a value: ")
b_value = input("b value: ")
c_value = input("c value: ")

# Calculate the solutions
answers = quadratic_solver(a_value, b_value, c_value)

# Format the solutions
formatted_answers = [format_solution(ans) for ans in answers]

# Print the solutions
print("The solutions are:")
for ans in formatted_answers:
    print(ans)