Last active
November 10, 2019 19:48
-
-
Save AhmedMourad0/2f3645f9fec69ea6727141dea3556d44 to your computer and use it in GitHub Desktop.
For college.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from Stack import Stack | |
def is_operand(token): | |
""" | |
checks if token consists completely of digits or letters | |
:return: true if token is either all digit or all letters (case insensitive), false otherwise | |
""" | |
return token.isalpha() or token.isdigit() | |
operator_precedence = { | |
'(': 1, | |
'-': 2, | |
'+': 2, | |
'*': 3, | |
'/': 3, | |
'^': 4 | |
} | |
def infix_to_prefix(infix): | |
operands = Stack() | |
operators = Stack() | |
def extract_one_expression(): | |
""" | |
extracts two operands and one operator and combines them into a single prefix expression | |
""" | |
operand2 = operands.pop() | |
operand1 = operands.pop() | |
operator = operators.pop() | |
return operator + " " + operand1 + " " + operand2 | |
# for every token in our infix expression | |
for i in range(len(infix)): | |
token = infix[i] | |
if is_operand(token): | |
# if it's not the first token and is preceded by an operand, we combine them into token | |
if i > 0 and is_operand(infix[i - 1]): | |
token = operands.pop() + token | |
# we push token (which may or may not have been changed) to the stack | |
operands.push(token) | |
elif token == '(': | |
# if it's an opening bracket '(', we push it into the operators stack directly ignoring precedence | |
operators.push(token) | |
elif token == ')': | |
# if it's a closing bracket ')', we keep extracting expressions until we hit the opening bracket '(' | |
while (not operators.is_empty()) and operators.peek() != '(': | |
# we extract an expression and push into the stack, so if we have a+b-c | |
# a+b will be converted to +ab and pushed into the operands stack | |
# then we push c to the operands stack and extract the top two operands (which now are +ab and c) | |
# to create the next expression | |
# combining them with our operator we get -+abc which is now pushed to the top of the operands stack | |
operands.push(extract_one_expression()) | |
# pop the opening bracket '(' from the operators stack | |
operators.pop() | |
else: | |
# reaching this point means our token is an operator | |
while (not operators.is_empty()) and operator_precedence[token] <= operator_precedence[operators.peek()]: | |
# we keep extracting expressions as mentioned above as long as the operators stack is not empty and | |
# our operator's precedence is less than or equal to the precedence of the top operator on the stack | |
operands.push(extract_one_expression()) | |
# we push our new operator into the operators stack | |
operators.push(token) | |
# we extract expressions from the remaining elements in our stacks combining them all into | |
# one expression in the operands stack which is our result | |
while not operators.is_empty(): | |
operands.push(extract_one_expression()) | |
# the one remaining expression in the operands stack is our result | |
return operands.peek() | |
while True: | |
print(infix_to_prefix(input())) | |
# `(A-B/C)*(A/K-L)` -> `* - A / B C - / A K L` | |
# `(452-72/3)*(99/100-13)` -> `* - 452 / 72 3 - / 99 100 13` | |
# `A*B+C/D` -> `+ * A B / C D` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from Stack import Stack | |
# a lambda is a function than can be passed as a parameter or returned from another function | |
# lambda param1, param2, param3: returned_expression | |
# this is a dictionary with strings as keys and functions as their corresponding values | |
operations = { | |
"+": lambda a, b: a + b, | |
"-": lambda a, b: a - b, | |
"*": lambda a, b: a * b, | |
"/": lambda a, b: a / b, | |
"^": lambda a, b: a ** b | |
} | |
def evaluate_prefix(prefix): | |
operands = Stack() | |
# we split the prefix by space to get our tokens then we reverse it | |
for token in reversed(prefix.split()): | |
# if it's a digit we push it into the operands stack as an int | |
if token.isdigit(): | |
operands.push(int(token)) | |
else: | |
# if it's an operator we pop the top two operands | |
operand1 = operands.pop() | |
operand2 = operands.pop() | |
# we get the function from our dictionary corresponding to this operator and | |
# we call it using our two operands as parameters | |
result = operations[token](operand1, operand2) | |
operands.push(result) | |
# the one remaining value in the operands stack is our result | |
return operands.peek() | |
while True: | |
print(evaluate_prefix(input())) | |
# `- + 7 * 4 5 + 2 0` -> `25` | |
# `- + 8 / 6 3 2` -> `8` | |
# `- + 7 * 4 50 + 20 10` -> `177` | |
# `- + 7 * 4 5 + 20 10` -> `-3` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Stack: | |
def __init__(self): | |
# creates an empty list as a private instance variable | |
self.__items = [] | |
def push(self, item): | |
# list#append adds an element to the end of the list | |
self.__items.append(item) | |
def pop(self): | |
# list#pop removes and returns the last element in the list | |
return self.__items.pop() | |
def peek(self): | |
# list[-1] returns the last element in a list | |
return self.__items[-1] | |
def is_empty(self): | |
return self.size() == 0 | |
def size(self): | |
return len(self.__items) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment