Variable not changing to preferred index

Viewed 55

I'm making a calculator program and I'm currently on implementing negatives. So if I input 1--1--1 into the program, it'll first split it into a series of operations and integers, so that will turn into [1, '-', '-', 1, '-', '-', 1]. Then the functions I'm writing now are supposed to put the negatives where they go, so the preferred output in this case would be [1, '-', -1, '-', -1]. Here are the functions so far:

def join_neg(lst):
    tempstr = ''
    tempint = 0
    neg_ndx = 256000
    for num in lst:
        if num == '-':
            neg_ndx = lst.index(num)
            break

    if neg_ndx != 256000:
        neg = lst[neg_ndx]
        potential_int = lst[neg_ndx + 1]
        if isinstance(potential_int, int):
            if potential_int > 0:
                tempstr = neg + str(potential_int)
                del lst[neg_ndx:neg_ndx + 2]
                tempint = int(tempstr)
                lst.insert(neg_ndx, tempint)
            elif potential_int <= 0:
                print(neg_ndx)
                return join_neg_two(lst, neg_ndx)
        elif isinstance(potential_int, str):
            neg = lst[neg_ndx + 1]
            potential_int = lst[neg_ndx + 2]
            tempstr = neg + str(potential_int)
            del lst[neg_ndx + 1:neg_ndx + 3]
            tempint = int(tempstr)
            lst.insert(neg_ndx + 1, tempint)

        return join_neg(lst)
    elif neg_ndx == 256000:
        return lst


def join_neg_two(lst, ndx):
    tempstr = ''
    tempint = 0
    neg_ndx = 256000
    ndx += 1
    print(ndx)
    for num in lst[ndx:]:
        if num == '-':
            neg_ndx = lst.index(num)
            break
    print(neg_ndx)
    if neg_ndx != 256000:
        neg = lst[neg_ndx]
        potential_int = lst[neg_ndx + 1]
        if isinstance(potential_int, int):
            if potential_int > 0:
                tempstr = neg + str(potential_int)
                del lst[neg_ndx:neg_ndx + 2]
                tempint = int(tempstr)
                lst.insert(neg_ndx, tempint)
            elif potential_int <= 0:
                return lst
        elif isinstance(potential_int, str):
            neg = lst[neg_ndx + 1]
            potential_int = lst[neg_ndx + 2]
            tempstr = neg + str(potential_int)
            del lst[neg_ndx + 1:neg_ndx + 3]
            tempint = int(tempstr)
            lst.insert(neg_ndx + 1, tempint)

        return join_neg(lst)
    elif neg_ndx == 256000:
        return lst

One thing to note is that the functions are supposed to do this with any minus it finds, provided the next index contains an integer, otherwise it continues on. So [1, '-', 1] should output [1, -1]. Another thing I think I should address is the fact that the variable neg_ndx is assigned to the value 256000, this is how the program knows that it's finished combining all the negatives, and can move onto the next set of functions. The issue I'm currently having is that in the join_neg_two function, (using the example [1, '-', '-', 1, '-', '-', 1] which will be passed to this function looking like this: [1, '-', -1, '-', '-', 1]) the for loop should start iterating at the -1 object in the list, so (I think) the variable neg_ndx should become 3 which will then be passed to the rest of the function, but it doesn't. It gets turned into 1 which messes up the rest of the function. Is there something wrong with the way I'm iterating through the list starting at a different index other than 0 or is it something else?

Last thing, I seem to do a bad job formatting code since the last time I asked a question I got a lot of people telling me that variables, style, etc. were pretty bad, so if you find that my style is incomprehensible and need clarification or anything worse than what you'd expect from a beginner, please let me know.

1 Answers

Sorry to hear that you had a bad experience when asking a question before. To avoid such comments in future, try to be more specific in your questions. Instead of giving long functions, try to find where you think that something goes wrong and try to isolate that part into a minimal example.

It is clear that you are trying to learn something. So never forget to put your learning goal into such a question. I guess you know that a simple eval could do the job and before people start shouting that this is dangerous, you should add some checks to not execute harmful code lines.

string = "1--1--1"
allowed = '0123456789+-*/()'
if set(string).issubset(allowed):
    result = eval(string)
else:
    raise ValueError("invalid input string")
print(result)

However, I guess you want to learn more about working with strings and how to extract pattern. Here, the build-in module re can help you. I admit that learning how regular expressions work is hard for beginners, but it is really worth it if you want to learn more about working with text data. See https://docs.python.org/3/library/re.html for the documentation and https://realpython.com/regex-python/ for a beginners tutorial.

Using this you can check if the input is a valid expression and split it accordingly:

import re

def split_input(string):
    number = "(-?\d+(?:\.\d+)?)"
    operator = f'({"|".join(map(re.escape, "+-*/"))})'
    pattern = f"^({number}{operator})*{number}$"
    sep = f"{number}{operator}"
    match = re.match(pattern, string)
    if match is None:
        raise ValueError("invalid input")
    return [item for item in re.split(sep, string) if item]

string = "1--2.2+-3*-4.4/-5"
print(split_input(string))

However, coming back to your code and your current obstacle. If I understand correctly, you have a list like [1, "-", "-", 1, "-", "-", 1] and you are looking for a function that applies the sign to the integer. First thing, I noticed in your code is that you delete elements from the list you are working on with indexes. This is generally a bad idea. Better create a new list from the old one, so your indexes remain meaningful. Even better is avoiding indexes at all. See the following:

lst = [1, "-", "-", 1, "-", "-", 1]
new_lst = [lst.pop()]

def apply_last_sign(stack):
    sign = stack.pop()
    number = stack.pop()

    if sign == '-':
        number *= -1
    elif sign not in "-+":
        raise ValueError

    stack.append(number)

while lst:
    item = lst.pop()
    if isinstance(new_lst[-1], str) and isinstance(item, str):
        apply_last_sign(new_lst)
    new_lst.append(item)

# check for potential sign at the beginning
if isinstance(new_lst[-1], str):
    apply_last_sign(new_lst)

new_lst.reverse()
print(new_lst)

Here, I just pop and append items to lists without any need for indexes. I hope the above lines and ideas will help you in learning Python.

Related