-1

I've written polish notation algorithm. But it doesn`t work properly, if there are the same operands between operator. If we run this code with current list ['a', '+', 'a', '*', 'b'], it will work properly, but if we change(b) on (a) it won't. The result in the first case is (a, a, b, *, +) and in the second (a, a, +, a, *). Why does it happen?

operators = ["+", "-"]
operators1 = ["*", "/"]
operators2 = ["^"]
operators3 = ["(", ")"]
all_operators = ["+", "-", "*", "/", "^"]


def get_priority(operator):
    if operator in operators:
        priority = 1
    if operator in operators1:
        priority = 2
    if operator in operators2:
        priority = 3
    if operator in operators3:
        priority = 4
return priority


def notation():
exit = []
stack = []
list = ['a', '+', 'a', '*', 'b']
for i in list:

    if i not in all_operators:
        exit.append(i)

    else:
        stack.append(i)
        while len(stack) > 1 and get_priority(stack[-2]) >= get_priority(stack[-1]):
            exit.append(stack.pop(-2))

    if i is list[-1]:
        while len(stack) > 0:
            exit.append(stack.pop())

print(exit)
    


notation()

 
python_newbie
  • 23
  • 1
  • 7
  • 1
    What does "change(b) on (a)" mean? – Scott Hunter Jun 28 '20 at 14:14
  • When you run your program with a debugger, what is the first thing it does that you didn't expect? – Scott Hunter Jun 28 '20 at 14:15
  • 1
    Welcome to [so]. Please note that your code as shown is malformed – it has at least two incorrectly indented blocks. Please [edit] your question to enable us to debug your *actual* code. See the [mcve] and [ask] pages how to best help us help you. – MisterMiyagi Jun 28 '20 at 14:17
  • 1
    What is `if i is list[-1]:` used for? – Scott Hunter Jun 28 '20 at 14:20
  • Note that your issue is *probably* due to the ``if i is list[-1]:`` line. This only triggers if the last element is identical to some other element - i.e. in ``['a', '+', 'a', '*', 'a']`` because ``list[0] is list[-1]`` and ``list[2] is list[-1]``. This line likely does not do what you want – ``is`` is the *identity* operator, and the identity of literal values is implementation defined. Did you mean to test whether the ``for`` loop is at the last element? – MisterMiyagi Jun 28 '20 at 14:21
  • @MisterMiyagi Thank you for your help. I thought that all elements were different objects. – python_newbie Jun 28 '20 at 14:45

1 Answers1

0

The error is i is list[-1] and it surfaces when the last element of the list is a value that occurs also earlier in the list. In the case of ['a', '+', 'a', '*', 'a'], the condition will be true on the first iteration of the loop (and the third, and the last). Obviously this will produce wrong results.

As you want to perform that while loop only when going through the last iteration of the for loop, you might as well move that while loop after the whole for block, and unconditionally.

I applied some other changes to your code that do not relate to your question, and are not fixes to the algorithm itself, but just seem better practice. And I removed the parentheses from the operator list, as your code does not support that feature yet (Polish notation should not include parentheses):

operator_priority = {
    "+": 1,
    "-": 1,
    "*": 2,
    "/": 2,
    "^": 3,
}

all_operators = list(operator_priority.keys())

def notation(tokens):
    result = []
    stack = []
    for token in tokens:
        if token not in all_operators:
            result.append(token)
        else:
            prio = operator_priority[token]
            while len(stack) > 0 and operator_priority[stack[-1]] >= prio:
                result.append(stack.pop())
            stack.append(token)
    while len(stack) > 0:
        result.append(stack.pop())
    return result
    
result = notation(['a', '+', 'a', '*', 'a'])
print(result)
trincot
  • 317,000
  • 35
  • 244
  • 286