-
-
Save cyvax/e8e1cac14f31505c14e02fff43d91813 to your computer and use it in GitHub Desktop.
Smart Calculator
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
# write your code here | |
from string import ascii_letters, digits | |
class Calculator: | |
def __init__(self): | |
self.variables = {} | |
while True: | |
self.user_input = input() | |
if self.user_input.startswith("/"): | |
msg = self.command() | |
elif self.user_input == "": | |
continue | |
elif self.user_input[0] in ascii_letters: | |
msg = self.process() | |
elif self.user_input[0] not in ascii_letters + digits: | |
msg = "Invalid expression" | |
else: | |
msg = self.calculate | |
if msg or msg == 0: | |
print(msg) | |
def command(self): | |
if self.user_input == "/exit": | |
print("Bye!") | |
exit(0) | |
elif self.user_input == "/help": | |
return "This program adds or subtracts numbers." | |
else: | |
return f"Unknown command" | |
@staticmethod | |
def add(a, b): | |
return int(a) + int(b) | |
@staticmethod | |
def sub(a, b): | |
return int(a) - int(b) | |
def split(self): | |
raw_splitted = list(self.user_input) | |
operators = ("+", "-") | |
buffer = [] | |
splitted = [] | |
for i in raw_splitted: | |
if i in operators and len(splitted) == 0: | |
buffer.append(i) | |
if i not in operators and len(splitted) == 0: | |
splitted.append(i) | |
elif i not in operators and len(buffer) == 1: | |
pos = buffer.pop() | |
splitted.append(f"{pos}{i}") | |
elif not i.isdigit() and not splitted[-1][-1].isdigit(): | |
splitted[-1] += i | |
elif i.isdigit() and splitted[-1][-1].isdigit(): | |
splitted[-1] += i | |
else: | |
splitted.append(i) | |
if len(splitted) == 1: | |
if splitted[0] == "-" and splitted[1].isdigit(): | |
return "".join(splitted), False | |
elif splitted[0] == "+" and splitted[1].isdigit(): | |
return splitted[1], True | |
elif len(splitted) == 1 and splitted[0][1:].isdigit(): | |
return splitted[0], True | |
elif len(splitted) == 1 and splitted[0].isdigit(): | |
return splitted[0], True | |
return "Invalid expression", True | |
return splitted, False | |
@property | |
def calculate(self): | |
calc_list, status = self.split() | |
if status: | |
return calc_list | |
if status: | |
return calc_list[0] | |
if len(calc_list) < 2: | |
return "Invalid expression" | |
calc_list.reverse() | |
result_list = [] | |
try: | |
a, method, b = (calc_list.pop() for _ in range(3)) | |
except IndexError: | |
return "Invalid expression" | |
if "+" in set(method): | |
result_list.append(self.add(a, b)) | |
elif "-" in set(method): | |
if len(method) % 2 == 0: | |
result_list.append(self.add(a, b)) | |
else: | |
result_list.append(self.sub(a, b)) | |
while len(calc_list) > 0: | |
a = result_list.pop() | |
method, b = (calc_list.pop() for _ in range(2)) | |
if "+" in set(method): | |
result_list.append(self.add(a, b)) | |
elif "-" in set(method): | |
if len(method) % 2 == 0: | |
result_list.append(self.add(a, b)) | |
else: | |
result_list.append(self.sub(a, b)) | |
return result_list[0] | |
def process(self): | |
self.user_input = self.user_input.replace(" ", "") | |
if "=" in self.user_input: | |
return self.process_variable() | |
else: | |
if len(self.user_input.split()) == 1 and not any(elem in list(self.user_input) for elem in ["+", "-"]): | |
if self.user_input in self.variables.keys(): | |
return self.print_variable() | |
else: | |
return "Unknown variable" | |
else: | |
return self.calculate_var() | |
def process_variable(self): | |
try: | |
var, value = self.user_input.split("=") | |
except ValueError: | |
return "Invalid assignment" | |
if not all(elem in list(ascii_letters) for elem in list(var)): | |
return "Invalid identifier" | |
else: | |
if self.is_digit(value): | |
self.variables[var] = value | |
elif not all(elem in list(ascii_letters) for elem in list(value)): | |
return "Invalid assignment" | |
else: | |
if value not in self.variables.keys(): | |
return "Unknown variable" | |
else: | |
self.variables[var] = self.variables[value] | |
return | |
def print_variable(self): | |
return self.variables[self.user_input] | |
def calculate_var(self): | |
calc_list = self.split_var() | |
variables = [elem for elem in set(calc_list) if elem in ascii_letters] | |
if not all(elem in self.variables.keys() for elem in variables): | |
return "Unknown variable" | |
for elem in range(len(calc_list)): | |
if calc_list[elem] in self.variables: | |
calc_list[elem] = self.variables[calc_list[elem]] | |
self.user_input = "".join(calc_list) | |
return self.calculate | |
def split_var(self): | |
raw_splitted = list(self.user_input) | |
operators = ("+", "-") | |
buffer = [] | |
splitted = [] | |
for i in raw_splitted: | |
if i in operators and len(splitted) == 0: | |
buffer.append(i) | |
elif i in operators and all(elem not in list(ascii_letters+digits) for elem in list(splitted[-1][-1])): | |
splitted[-1] += i | |
elif i not in operators and len(buffer) == 1: | |
pos = buffer.pop() | |
splitted.append(f"{pos}{i}") | |
else: | |
splitted.append(i) | |
return splitted | |
@staticmethod | |
def is_digit(value): | |
try: | |
int(value) | |
return True | |
except ValueError: | |
return False | |
Calculator() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment