-
-
Notifications
You must be signed in to change notification settings - Fork 46.9k
Updated postfix_evaluation.py to support Unary operators #8787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
5bbcee5
Updated postfix_evaluation.py to support Unary operators and floating…
arijitde92 b4565e0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] b985141
Updated postfix_evaluation.py to support Unary operators and floating…
arijitde92 800b07a
Updated postfix_evaluation.py to support Unary operators and floating…
arijitde92 70fd7fd
Fixed return type hinting required by pre commit for evaluate function
arijitde92 ef175af
Changed line 186 to return only top of stack instead of calling the g…
arijitde92 de92865
Merge branch 'TheAlgorithms:master' into master
arijitde92 d6874ad
Made the requested changes
arijitde92 b4521ea
Fixes #8754, #8724 Updated postfix_evaluation.py
arijitde92 b4f51a6
Fixes #8754, #8724 Updated postfix_evaluation.py
arijitde92 9a15148
Fixes #8754, #8724 Updated the parse_token function of postfix_evalua…
arijitde92 c11b18f
Fixes #8754, #8724 Updated postfix_evaluation.py
arijitde92 b2bb0af
Update postfix_evaluation.py
cclauss b0c44a6
Update postfix_evaluation.py
cclauss d3f4ee8
Update postfix_evaluation.py
cclauss 0b1627a
Update postfix_evaluation.py
cclauss 51df05c
Update postfix_evaluation.py
cclauss File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,11 @@ | ||
""" | ||
The Reverse Polish Nation also known as Polish postfix notation | ||
or simply postfix notation. | ||
https://en.wikipedia.org/wiki/Reverse_Polish_notation | ||
Classic examples of simple stack implementations | ||
Valid operators are +, -, *, /. | ||
Each operand may be an integer or another expression. | ||
|
||
Output: | ||
|
||
Enter a Postfix Equation (space separated) = 5 6 9 * + | ||
|
@@ -17,52 +24,197 @@ | |
Result = 59 | ||
""" | ||
|
||
import operator as op | ||
|
||
def get_number(data: str) -> tuple[bool, int] | tuple[bool, float] | tuple[bool, str]: | ||
""" | ||
Converts the given data to appropriate number if it is indeed a number, else returns | ||
the data as it is with a False flag. This function also serves as a check of whether | ||
the input is a number or not. | ||
|
||
Parameters | ||
---------- | ||
data : str | ||
The data which needs to be converted to the appropriate number | ||
|
||
Returns | ||
------- | ||
bool, int or float | ||
Returns a tuple of (a, b) where 'a' is True if data is indeed a number (integer | ||
or numeric) and 'b' is either an integer of a floating point number. | ||
If 'a' is False, then b is 'data' | ||
""" | ||
int_val = 0 | ||
float_val = 0.0 | ||
try: | ||
int_val = int(data) | ||
return True, int_val | ||
except ValueError: | ||
try: | ||
float_val = float(data) | ||
return True, float_val | ||
except ValueError: | ||
return False, data | ||
|
||
|
||
def is_operator(data: str) -> bool: | ||
""" | ||
Checks whether a given input is one of the valid operators or not. | ||
Valid operators being '-', '+', '*', '^' and '/'. | ||
|
||
Parameters | ||
---------- | ||
data : str | ||
The value that needs to be checked for operator | ||
|
||
Returns | ||
------- | ||
bool | ||
True if data is an operator else False. | ||
""" | ||
return data in ["-", "+", "*", "^", "/"] | ||
|
||
|
||
def solve(post_fix): | ||
def evaluate(post_fix: list, verbose: bool = False) -> int | float | str | None: | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Function that evaluates postfix expression using a stack. | ||
>>> evaluate(["2", "1", "+", "3", "*"]) | ||
9 | ||
>>> evaluate(["4", "13", "5", "/", "+"]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add doctests for:
|
||
6.6 | ||
>>> evaluate(["2", "-", "3", "+"]) | ||
1 | ||
>>> evaluate([]) | ||
0 | ||
|
||
Parameters | ||
---------- | ||
post_fix : list | ||
The postfix expression tokenized into operators and operands and stored as a | ||
python list | ||
|
||
verbose : bool | ||
Display stack contents while evaluating the expression if verbose is True | ||
|
||
Returns | ||
------- | ||
int | ||
The evaluated value | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
stack = [] | ||
div = lambda x, y: int(x / y) # noqa: E731 integer division operation | ||
opr = { | ||
"^": op.pow, | ||
"*": op.mul, | ||
"/": div, | ||
"+": op.add, | ||
"-": op.sub, | ||
"^": lambda p, q: p**q, | ||
"*": lambda p, q: p * q, | ||
"/": lambda p, q: p / q, | ||
"+": lambda p, q: p + q, | ||
"-": lambda p, q: p - q, | ||
} # operators & their respective operation | ||
if len(post_fix) > 0: | ||
if verbose: | ||
# print table header | ||
print("Symbol".center(8), "Action".center(12), "Stack", sep=" | ") | ||
print("-" * (30 + len(post_fix))) | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for x in post_fix: | ||
is_number, x = get_number(x) | ||
if is_number: # if x is a number (integer, float) | ||
stack.append(x) # append x to stack | ||
tianyizheng02 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if verbose: | ||
# output in tabular format | ||
print( | ||
str(x).rjust(8), | ||
("push(" + str(x) + ")").ljust(12), | ||
stack, | ||
sep=" | ", | ||
) | ||
elif is_operator(x): | ||
# If only 1 value is inside stack and + or - is encountered | ||
# then this is unary + or - case | ||
if x in ["-", "+"] and len(stack) < 2: | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
b = stack.pop() # pop stack | ||
if x == "-": | ||
stack.append(-b) # negate b and push again into stack | ||
else: # when x is unary + | ||
stack.append(b) | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if verbose: | ||
# output in tabular format | ||
print( | ||
"".rjust(8), | ||
("pop(" + str(b) + ")").ljust(12), | ||
stack, | ||
sep=" | ", | ||
) | ||
print( | ||
str(x).rjust(8), | ||
("push(" + str(x) + str(b) + ")").ljust(12), | ||
stack, | ||
sep=" | ", | ||
) | ||
else: | ||
b = stack.pop() # pop stack | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if verbose: | ||
# output in tabular format | ||
print( | ||
"".rjust(8), | ||
("pop(" + str(b) + ")").ljust(12), | ||
stack, | ||
sep=" | ", | ||
) | ||
|
||
a = stack.pop() # pop stack | ||
if verbose: | ||
# output in tabular format | ||
print( | ||
"".rjust(8), | ||
("pop(" + str(a) + ")").ljust(12), | ||
stack, | ||
sep=" | ", | ||
) | ||
# evaluate the 2 values popped from stack & push result to stack | ||
stack.append(opr[x](a, b)) | ||
if verbose: | ||
# output in tabular format | ||
print( | ||
str(x).rjust(8), | ||
("push(" + str(a) + str(x) + str(b) + ")").ljust(12), | ||
stack, | ||
sep=" | ", | ||
) | ||
else: | ||
print(f"{x} is neither a number, nor a valid operator") | ||
break | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# If everything executed correctly,the stack will contain | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# only one element which is the result | ||
result = stack[0] if len(stack) == 1 else None | ||
return result | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return 0 | ||
|
||
|
||
def is_yes(val: str) -> bool: | ||
""" | ||
Function that checks whether a user has entered any representation of a Yes (y, Y). | ||
Any other input is considered as a No. | ||
|
||
Parameters | ||
----------- | ||
val : str | ||
The value entered by user | ||
|
||
# print table header | ||
print("Symbol".center(8), "Action".center(12), "Stack", sep=" | ") | ||
print("-" * (30 + len(post_fix))) | ||
|
||
for x in post_fix: | ||
if x.isdigit(): # if x in digit | ||
stack.append(x) # append x to stack | ||
# output in tabular format | ||
print(x.rjust(8), ("push(" + x + ")").ljust(12), ",".join(stack), sep=" | ") | ||
else: | ||
b = stack.pop() # pop stack | ||
# output in tabular format | ||
print("".rjust(8), ("pop(" + b + ")").ljust(12), ",".join(stack), sep=" | ") | ||
|
||
a = stack.pop() # pop stack | ||
# output in tabular format | ||
print("".rjust(8), ("pop(" + a + ")").ljust(12), ",".join(stack), sep=" | ") | ||
|
||
stack.append( | ||
str(opr[x](int(a), int(b))) | ||
) # evaluate the 2 values popped from stack & push result to stack | ||
# output in tabular format | ||
print( | ||
x.rjust(8), | ||
("push(" + a + x + b + ")").ljust(12), | ||
",".join(stack), | ||
sep=" | ", | ||
) | ||
|
||
return int(stack[0]) | ||
Returns | ||
------- | ||
bool | ||
True if Yes, otherwise False | ||
""" | ||
return val in ["Y", "y"] | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
if __name__ == "__main__": | ||
Postfix = input("\n\nEnter a Postfix Equation (space separated) = ").split(" ") | ||
print("\n\tResult = ", solve(Postfix)) | ||
loop = True | ||
# Creating a loop so that user can evaluate postfix expression multiple times | ||
while loop: | ||
expression = input("Enter a Postfix Expression (space separated): ").split(" ") | ||
choice = input("Do you want to see stack contents while evaluating? [y/N]: ") | ||
display = is_yes(choice) | ||
output = evaluate(expression, display) | ||
if output is not None: | ||
print("Result = ", output) | ||
choice = input("Do you want to enter another expression? [y/N]: ") | ||
loop = is_yes(choice) | ||
arijitde92 marked this conversation as resolved.
Show resolved
Hide resolved
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.