Python program to convert infix to prefix notation - python

I keep on getting an IndexError: list index out of range, return self.data[-1] # the last element in the list; I think I know what is causing this but I have no clue how to fix it
Here is the Stack Class I used:
class Stack:
# LIFO Stack implementation using a Python list as underlying storage.
def __init__(self):
self.data =[]
def __len__(self):
return len(self.data)
def is_empty(self):
return len(self.data)==0
def push(self, e):
self.data.append(e)
def top(self):
return self.data[-1]
def pop(self):
return self.data.pop()
And the corresponding code I made:
def operatorpriority(x):
if x == "+" or x == "-":
return 1
elif x == "*" or x == "/":
return 2
else:
return 3
return 0
def polishnotation(A):
# Converts Infix to Prefix Notation
stack = Stack()
stack.push(')')
A = A + '('
output = ""
for i in range(len(A)-1, -1, -1):
print(i)
if A[i].isnumeric() == True:
output+=A[i]
elif A[i] == ")":
stack.push(A[i])
elif A[i] == "-" or A[i] == "+" or A[i] == "*" or A[i] == "/" or A[i] == "^":
if A[i] == "^":
while operatorpriority(A[i]) <= operatorpriority(stack.top()):
output+=stack.pop()
else:
while operatorpriority(A[i]) < operatorpriority(stack.top()):
output+=stack.pop()
stack.push(A[i])
elif A[i] == "(":
while stack.is_empty()== False:
if stack.top() != "(":
output+=stack.pop()
stack.pop()
while stack.is_empty()== False:
output+=stack.pop()
print(output)
InfixInput = input("Input infix notation: ")
polishnotation(InfixInput)
Sample Input:
(a+b)*(c-d)
Expected Output:
*+ab-cd

You have A = A + '('. That adds at the wrong end. Just do A = '('+A+')' and skip the extra push.
You are giving ')' the same priority as '^'. In operatorpriority, your else: should be elif x =='^':.
In your elif A[i] == "(" clause, you are popping until '('. That's the wrong type of parens. And you don't break out of that loop until the stack is empty. You need to break when you get to a ')'.
Your example shows (a+b)*(c+d), but your code only allows digits. I haven't changed that.
This works:
class Stack:
# LIFO Stack implementation using a Python list as underlying storage.
def __init__(self):
self.data =[]
def __len__(self):
return len(self.data)
def is_empty(self):
return len(self.data)==0
def push(self, e):
self.data.append(e)
def top(self):
return self.data[-1]
def pop(self):
return self.data.pop()
def operatorpriority(x):
if x in "+-":
return 1
elif x in "*/":
return 2
elif x in "^":
return 3
return 0
def polishnotation(A):
# Converts Infix to Prefix Notation
stack = Stack()
A = '(' + A + ')'
output = ""
for c in A[::-1]:
print(c)
if c.isnumeric():
output+=c
elif c == ")":
stack.push(c)
elif c in "+-*/^":
if c == "^":
while operatorpriority(c) <= operatorpriority(stack.top()):
output+=stack.pop()
else:
while operatorpriority(c) < operatorpriority(stack.top()):
output+=stack.pop()
stack.push(c)
elif c == "(":
while not stack.is_empty():
c1 = stack.pop()
if c1 == ')':
break
output+=c1
while not stack.is_empty():
output+=stack.pop()
return output
print(polishnotation('(3+4)*(5+6)'))

Related

TypeError: 'Stack' object is not subscriptable

class Stack:
max = 10
def __init__(self):
self.Stack =[]
self.top = 0
def getter(self):
print(self.Stack)
def push(self):
if (self.top == self.max):
print("Stack Overflow\n",
"Please pop out the Stack to enter new values :)")
else:
self.Stack.append(exp[index])
self.top += 1
def popup(self):
if (self.top == 0):
print(" Stack Underflow\n", "push some element to pop some")
else:
self.top -= 1
return self.Stack.pop()
allow = ['%', '/', '*', '-', '+', '(', ')','**']
precedencse = {'+': 1, '-': 1, '*': 2, '/': 2, '%': 3,'**':4,'(':0,')':0}
newexp = str()
exp = input("Enter the expression")
index = int(0)
stack = Stack()
while (True):
if (exp[index].isalpha() == True):
newexp = exp[index]
index += 1
elif (exp[index] in allow):
if (stack.top == 0 or exp[index] == '(' or exp[index] == ')' or precedencse[exp[index]] > precedencse[stack[stack.top]] == True):
stack.push()
index += 1
if(stack[stack.top] == ')' and '(' in stack == True):
for i in range(stack.index('(')-1, stack.top):
newexp = stack.popup()
newexp.replace('(','')
newexp.replace(')','')
elif (precedencse[exp[index]] < precedencse[stack.top] == True or precedencse[exp[index]]==precedencse[stack.top] == True):
newexp = stack.popup()
stack.push()
else:
print("You Entered worng character in the expression")
break
print(newexp)
I am trying to do infix to postfix conversion algorithm
when I am creating Stack=[] inside the class it gives the following error but when i create the same stack=[] outside the class it give AttributeError: 'Stack' object has no attribute 'append'
please explain me the solution. am a rookie programmer

Performing arbitrary arithmetic operations that a user provides to the system using stack (stack implementation being done with linked lists)

I'm using the following code to perform stack implementation in the case of solving arbitrary arithmetic operations:
def precedence(op):
if op == '+' or op == '-':
return 1
if op == '*' or op == '/':
return 2
return 0
def operation(a, b, op):
if op == '+': return a + b
if op == '-': return a - b
if op == '*': return a * b
if op == '/': return a / b
def evaluate(tokens):
# This is a stack to store integer values
values = []
# This stack stores operators
ops = []
i = 0
while i < len(tokens):
if tokens[i] == ' ':
i += 1
continue
elif tokens[i] == '(':
ops.append(tokens[i])
elif tokens[i].isdigit():
val = 0
while (i < len(tokens) and
tokens[i].isdigit()):
val = (val * 10) + int(tokens[i])
i += 1
values.append(val)
i -= 1
elif tokens[i] == ')':
while len(ops) != 0 and ops[-1] != '(':
val2 = values.pop()
val1 = values.pop()
op = ops.pop()
values.append(operation(val1, val2, op))
ops.pop()
else:
while (len(ops) != 0 and
precedence(ops[-1]) >=
precedence(tokens[i])):
val2 = values.pop()
val1 = values.pop()
op = ops.pop()
values.append(operation(val1, val2, op))
ops.append(tokens[i])
i += 1
while len(ops) != 0:
val2 = values.pop()
val1 = values.pop()
op = ops.pop()
values.append(operation(val1, val2, op))
return values[-1]
if __name__ == "__main__":
ask = input('Enter your expression here: ')
print(f"\nThe answer is {evaluate(ask)}")
But I have no clue how to translate this implementation of stack using linked list.
Can anyone help me? Or provide me with links that would be helpful in explaining stack using linked lists ?
Thanks!
class LLstack:
def __init__(self):
self.numNodes = 0
self.tail = None
def __iter__(self):
self.n = self.numNodes
self.index = self.tail
return self
def __next__(self):
if (self.n == self.numNodes):
self.n-=1
return self.index.val
if self.n>0:
self.n-=1
self.index = self.index.next
return self.index.val
else:
raise StopIteration
def push(self,val):
self.numNodes+=1
if (self.tail!=None):
temp = self.Node(val)
temp.next = self.tail
self.tail = temp
else:
self.tail = self.Node(val)
def pop(self):
if (self.numNodes==0):
return None
self.numNodes-=1
val = self.tail.val
self.tail = self.tail.next
return val
def size(self):
return self.numNodes
class Node:
def __init__(self,val):
self.val = val
self.next = None
if __name__== "__main__":
stack = LLstack()
for i in range(100):
stack.push(LLstack())
i = iter(stack)
for x in i:
print(x)
https://algs4.cs.princeton.edu/13stacks/
Not sure if this is what you are looking for.

List has no items to pop however there was something there?

Trying to make a brainfuck interpreter in python from scratch just for fun, I'm almost done with the code however this small error is coming up whenever I try interpreting ",[>++++<]" Which is supposed to input a number, and multiply it by 4. It stops and gets this error
File ".\bfInterpreter.py", line 42, in endWhile
if self.stack[self.pointer]: self.place = self.inWhile.pop(-1)
IndexError: pop from empty list
Any ideas?
here is the code that the error is in:
import sys
import time
class Operator:
def __init__(self) -> None:
self.pointer = 0
self.place = 0
self.inWhile = []
self.stack = [0]
def plus(self):
self.stack[self.pointer]+=1
def minus(self):
self.stack[self.pointer]-=1
def left(self):
if self.pointer > 0: self.pointer -= 1
else: raise IndexError
def right(self):
self.pointer += 1
try: self.stack[self.pointer] = 0
except: self.stack.append(0)
def output(self):
print(ascii(self.stack[self.pointer]))
def inp(self):
val = input("Num: ")
try: self.stack[self.pointer] = int(val)
except:
print("Please input a number")
self.inp()
def startWhile(self):
self.inWhile.append(self.place)
print(self.inWhile)
def endWhile(self):
print(self.inWhile)
if self.stack[self.pointer]: self.place = self.inWhile.pop(-1)
def interpret(self, bf):
self.place = 0
while self.place < len(bf):
if bf[self.place] == "+": self.plus()
elif bf[self.place] == "-": self.minus()
elif bf[self.place] == "<": self.left()
elif bf[self.place] == ">": self.right()
elif bf[self.place] == "[": self.startWhile(bf)
elif bf[self.place] == "]": self.endWhile()
elif bf[self.place] == ",": self.inp()
elif bf[self.place] == ".": self.output()
else: raise SyntaxError
self.place += 1
print(self.stack)
def main():
start = time.time()
op = Operator()
op.interpret(",[>++++<]")
print(f"Ended in {time.time() - start} second(s)")
if __name__ == "__main__": main()
Edit: self.stack is basically the memory that brainfuck is allowed to access and edit, so the "[" starts a while loop, checking if a certain spot in the stack has reached 0 every cycle, and if it's not 0, it repeats the code in the brackets
The main problem is self.inWhile.pop(-1) in command ] - it removes value from list and in next loop this list is empty - so pop(-1) raises your error message.
But there is more mistakes and problems in [ and ].
All commands runs self.place += 1 but ] shouldn't do this because this way it jump to first command after [ but it should run again [. Maybe if it would run again [ then it could add again value to inWhile and self.inWhile.pop(-1) whouldn't make problem.
But there is other problem with [ - it should check if value is 0 and jump to first command after ]. It would need another list to remember position of ] but it seems more complicated - because if at start value is 0 then it couldn't yet run ] and it couldn't add position to list. Better is to search matching ] in string with commands. The same method I used to search [ (instead of using inWhile).
Other problem is > you always try to set stack[place] = 0 but if you run > and next < and again > then stack[place] may already exists and it may have some value and stack[place] = 0 may remove this value. I rather use while loop with pointer >= len(stack) to append values only if stack is really too short.
Other problem is that program in branfuck runs loop forever because it doesn't have - to decreate inputed value. It needs also >. after loop to display result.
,[->++++<]>.
My version without inWhile but with loop which search matching [ or matching ].
import sys
import time
class Operator:
def __init__(self):
self.place = 0 # command place
self.pointer = 0 # stack pointer
self.stack = [0]
def input(self):
#print('[DEBUG] input')
while True:
val = input("Number: ")
try:
self.stack[self.pointer] = int(val)
break
except:
print("Please input a integer number")
def output(self):
#print('[DEBUG] output')
print(ascii(self.stack[self.pointer]))
def plus(self):
#print('[DEBUG] plus')
self.stack[self.pointer] += 1
def minus(self):
#print('[DEBUG] minus')
self.stack[self.pointer] -= 1
def left(self):
#print('[DEBUG] left')
if self.pointer > 0:
self.pointer -= 1
else:
raise IndexError
def right(self):
#print('[DEBUG] right')
self.pointer += 1
while len(self.stack) <= self.pointer:
self.stack.append(0)
def start_loop(self):
#print('[DEBUG] start_loop')
#print('self.place:', self.place)
if self.stack[self.pointer] == 0:
# find matching `]` to jump to next command after `]`
counter = 1
while counter > 0:
self.place += 1
char = self.bf[self.place]
if char == '[':
counter += 1
elif char == ']':
counter -= 1
#print('counter:', counter)
def end_loop(self):
#print('[DEBUG] end_loop')
#print('self.place:', self.place)
# find matching `[` to run again `[` and all loop
counter = 1
while counter > 0:
self.place -= 1
char = self.bf[self.place]
if char == '[':
counter -= 1
elif char == ']':
counter += 1
#print('counter:', counter)
def interpret(self, bf):
self.bf = bf
self.place = 0
while self.place < len(bf):
char = self.bf[self.place]
#print('[DEBUG] interpret:', self.place, bf[self.place])
if char == ",":
self.input()
self.place += 1
elif char == ".":
self.output()
self.place += 1
elif char == "+":
self.plus()
self.place += 1
elif char == "-":
self.minus()
self.place += 1
elif char == "<":
self.left()
self.place += 1
elif char == ">":
self.right()
self.place += 1
elif char == "[":
self.start_loop()
self.place += 1
elif char == "]":
self.end_loop()
# it has to be without `self.place += 1`
else:
raise SyntaxError
print('stack:', self.stack)
def main():
start = time.time()
op = Operator()
op.interpret(",[->++++<]>.") # input*4
#op.interpret(",[->+>++>+++>++++<<<<]>.>.>.>.") # input*1, input*2, input*3, input*4
#op.interpret(",[->+<>>++<<>>>+++<<<>>>>++++<<<<]>.>.>.>.") # input*1, input*2, input*3, input*4
end = time.time()
print(f"Ended in {end - start:.2f} second(s)")
if __name__ == "__main__":
main()

Stack and evaluate postfix

I was wondering if anyone can help with this Stack question
there are 2 example in the main function and the answer should be 1024 and 4096, but I will get 100 and 144
the issue must be in evaluate_postfix definition becuase I know the Stack class is working
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
def evaluate_postfix(text):
s = Stack()
for element in text:
plus = None
if element.isdigit():
s.push(int(element))
elif element == '^':
plus = s.pop() ** s.pop()
elif element == "+":
plus = s.pop() + s.pop()
elif element == "-":
plus = s.pop() - s.pop()
elif element == "*":
plus = s.pop() * s.pop()
elif element == "/":
plus = s.pop() / s.pop()
if plus is not None:
s.push(plus)
return s.pop()
def main():
print(evaluate_postfix(['2', '10', '^']))
print(evaluate_postfix(['2', '4', '3', '*', '^']))
main()
You're poping the right elements, but in the wrong order:
s.pop() ** s.pop()
Once your program reaches that line, for the first example, the stack will look like this: ['2', '10']. It pops 10, then 2, then raises 10 to the power of 2. Instead, you can use:
right = s.pop()
left = s.pop()
left ** right
You'll receive the desired answer, 1024. The same principle applies to the other operators.

adding parenthesis in recursive function

I'm simply looking to add a parenthesis at the end of my recursive function.. I'm literally just missing the final parenthesis, but I can't figure out how to add it in! Any help is greatly appreciated!
My code:
def sum( n ):
if n == 0:
return '1'
elif n == 1:
return '(1+1)'
elif n == 2:
return '((1+1)+(1+1))'
elif n == 3:
return '(((1+1)+(1+1))+((1+1)+(1+1)))'
else:
return '((((1+1)+(1+1))+((1+1)+(1+1)))' + ')'sum_power2( n - 1 )
Just switch the order in the last row, so it would be
def sum_power2( n ):
if n == 0:
return '1'
elif n == 1:
return '(1+1)'
elif n == 2:
return '((1+1)+(1+1))'
elif n == 3:
return '(((1+1)+(1+1))+((1+1)+(1+1)))'
else:
return '((((1+1)+(1+1))+((1+1)+(1+1)))' + sum_power2( n - 1 )+')'
Try this:
def sum_power(n,tmp=''):
tmp = '1' if not tmp else '(' + tmp + '+' + tmp + ')'
if n == 0:
return tmp
else:
n -= 1
return sum_power(n,tmp)
print(sum_power(2))

Categories

Resources