I've recently been assigned an assignment to create a word calculator, and given my knowledge in python is still quite lacking, I want to ask if anybody has any better ideas for any possible solutions.
The question is here:
Jimmy has invented a new kind of calculator that works with words
rather than numbers.
Input is read from stdin and consists of up to 1000 commands, one per line.
Each command is a definition, a calculation or
clear.All tokens within a command are separated by single spaces.
A definition has the format
def x ywhere x is a variable name and y is an integer in the range [-1000, 1000].Existing definitions are replaced by new ones i.e. if x has been defined previously, defining x again erases its old definition.
Variable names consist of 1-30 lowercase characters.
No two variables are ever defined to have the same value at the same time.
The
clearcommand erases all existing variable definitions.A calculation command starts with the word
calc, and is followed by one or more variable names separated by addition or subtraction operators.The end of a calculation command is an equals sign.
The goal is to write a program for Jimmy's calculator. Some rules are:
- The program should produce no output for definitions, but for calculations it should output the value of the calculation.
- Where there is no word for the result, or some word in a calculation has not been defined, then the output should be
unknown. (The wordunknownis never used as a variable name.)- Your solution may only import content from the
sysmodule.- Your solution may not use the
eval()function.Here is a sample input below:
calc foo + bar = def bar 7 def programming 10 calc foo + bar = def is 4 def fun 8 calc programming - is + fun = def fun 1 calc programming - is + fun = clearAnd the corresponding output:
foo + bar = unknown foo + bar = programming programming - is + fun = unknown programming - is + fun = bar
My current solution is this:
import sys
lines = sys.stdin.readlines()
d_define = {}
numsInDict = []
operators = ["+", "-", "="]
# IN : word to checked it is in the dictionary
# OUT : returns unknown or value for word
def lookup(word):
if word in d_define:
return d_define[word]
else:
return "unknown"
# IN : answer to check if there is a word assigned to it a dictionary
# OUT : returns unknown or word assigned to answer
def getAnswer(answer):
for k, v in d_define.items():
if v == answer:
return k
return "unknown"
# IN : All values to calc (includes operators)
# OUT : print unknown or word if in dict
def calc(args):
equation = 0
lastOperator = "+"
for word in args:
if word not in operators:
res = lookup(word)
if res == "unknown":
return "unknown"
else:
#print(res)
if lastOperator == "+":
equation += res
else:
equation -= res
else:
lastOperator = word
if equation in numsInDict:
res = getAnswer(equation)
return res
else:
return "unknown"
# IN : word to be added and its value
# OUT : updated dictionary
def define(word, num):
num = int(num)
if num in numsInDict or word in d_define:
# print(f'NEEDS REPLACE')
# print(f'same value -> {num in numsInDict}')
# print(f'same word -> {word in d_define}')
# print(f'same word -> {d_define}')
# print(f'same word -> {numsInDict}')
topop = ""
for k, v in d_define.items():
if k == word:
d_define[word] = num # Update Word with new value
elif v == num:
topop = k # Saves value to pop later
if topop != "":
d_define.pop(topop)
d_define[word] = num
else:
d_define[word] = num
numsInDict.append(num)
#print(f'{word} - {d_define[word]}')
for line in lines:
#print(f'-------------------------------------- LOOP START ------------------------------------')
line = line.rstrip().split()
#print(f'Line Split - {line}')
if len(line) == 3 and line[0] == "def":
define(line[1], line[2])
elif len(line) > 1 and line[len(line) - 1] == "=":
result = calc(line[1:])
print(f'{" ".join(line[1:]) + " " + result}')
elif len(line) == 1 and line[0] == "clear":
d_define = {}
wordsInDict = []
numsInDict = []
#print(f'Cleared d_define - {d_define} {wordsInDict}')
#print(d_define)
#print(f'--------------------------------------- LOOP END -------------------------------------')
It does feel quite clunky but it gets the job done. I am just wondering if anybody has any better ways in which it could be improved upon - and hearing your own different approaches and solutions would be awesome!