Input Loop - Dictionary Lookup and Recursion Calculator in Python - python

brand new at Python, and been experimenting with various calculator code methods in Python.
I found the following code:
from operator import pow, truediv, mul, add, sub
operators = {
'+': add,
'-': sub,
'*': mul,
'/': truediv
}
def calculate(s):
if s.isdigit():
return float(s)
for c in operators.keys():
left, operator, right = s.partition(c)
if operator in operators:
return operators[operator](calculate(left), calculate(right))
calc = input("Type calculation:\n")
print("Answer: " + str(eval(calc)))
and I'm just wondering how one would formulate an input loop for this one.

from operator import pow, truediv, mul, add, sub
operators = {
'+': add,
'-': sub,
'*': mul,
'/': truediv
}
def calculate(s):
if s.isdigit():
return float(s)
for c in operators.keys():
left, operator, right = s.partition(c)
if operator in operators:
return operators[operator](calculate(left), calculate(right))
cont = 'y'
while cont.lower() == 'y':
calc = input("Type calculation:\n")
print("Answer: " + str(eval(calc)))
cont = input("Do you want to continue? (y/n)")
It would be good to add more validations to the code... like ensuring that only one operator exists and that there are numbers on either side of the operator inside the calc function.
Also, you are importing power but don't have a symbol for it. Can use '^' if you haven't already? It is easier than using '**' which python uses.

The script will ask you continuosly for operation to compute as follows:
while True:
calc = input("Type calculation (C to exit):\n")
if calc.upper().strip() == "C":
break
print("Answer: " + str(eval(calc)))
Note that, as it is, the code is extremely fragile, given that anything which cannot be reconducted to a number operator number pattern (or "C"), will need to be treated. You could use pattern matching to check if the operation is valid before passing to eval first, and manage bad cases as you wish.

Related

How can I draw from a list of math operators and have it interpreted as a math operation and not a string? [duplicate]

This question already has answers here:
Python creating a calculator
(4 answers)
Closed 2 years ago.
I'm trying to use this loop to condense existing code, but storing the operators in a list and then drawing from it doesn't work, it throws this error: TypeError: unsupported operand type(s) for +: 'float' and 'str'
I understand that it's not interpreting the operator variable as an actual math operation, it's reading it as a str, but I'm not sure how to fix that. Here's the complete loop I've built.
operators = ["+", "-", "*", "/", "^"]
for operator in operators:
math_expression = input("Enter your math expression, or (q)uit: ")
print("Operator found " + operator)
operator_position = math_expression.find(operator) # find operator
print("Found " + operator + "operator at index " + str(operator_position))
first_number = math_expression[:operator_position] # find first number
second_number = math_expression[operator_position + 1:] # find second number
answer = float(first_number) + operator + float(second_number)
The operator module has functions that represent basic operations, such as the ones you're looking for.
Here, we
stuff those operators into a dict
loop over the symbol and function for each operator
if the symbol is found in the user input, the str.partition() function splits the string into segments before and after the symbol...
and then we just call the function.
import operator
operators = {
"+": operator.add,
"-": operator.sub,
"*": operator.mul,
"/": operator.truediv,
"^": operator.pow,
}
expression = "5 + 3" # elided input to make debugging faster
for symbol, func in operators.items():
if symbol in expression:
a, _, b = expression.partition(symbol)
answer = func(float(a), float(b))
print(answer)
break

Not resulting the way I want it to [duplicate]

This question already has answers here:
Testing user input against a list in python
(4 answers)
Closed 2 years ago.
operator = input("Please select one option: add/subtract/multiply/divide: ")
if operator != "add" or operator != "subtract" or operator != "multiply" or operator != "divide":
print("The option you chose (" + operator + ") is not valid\nPlease try this program again.")
sys.exit()
Result:
Please select one option: add/subtract/multiply/divide: add
The option you chose (add) is not valid
Please try this program again.
You're confusing how boolean algebra works.
operator != "add" or operator != "subtract" or operator != "multiply" or operator != "divide"
This will return true if operator is not either of add/subtract/multiply/divide.
So when you enter add, operator != "add" returns false, but the next one - operator != "subtract" returns true. Since it is an or operator, only one of all the expressions need to return true, for the whole expression to return true.
You should instead do-
operator != "add" and operator != "subtract" and operator != "multiply" and operator != "divide"
In simple english, that reads "return true if operator is none of add/subtract/multiply/divide"
Or more simply, using the in operator-
operator not in ["add", "subtract", "multiply", "divide"]
Which in simple english, reads "return true if operator is not an element in the list ["add", "subtract", "multiply", "divide"]"

How could I set up this variable properly? - Python

How could I set a variable up for +, - and *?
example of what I'm trying to do for subtraction
difficulty = '-'
FinalAnswer=((Answer1) (Difficulty) (Answer2))
I'm sure this is actually super simple and I'm having a massive brain fart.
The cleanest approach here is to use operator, e.g.:
import operator
operators = {'+': operator.add, '-': operator.sub}
x = operators['-'](a, b)
If you need to evaluate a string like 10 + 3, you could use eval(), e.g.:
s = '10 + 3'
eval(s)
As pointed out in the comment by #Błotosmętek, you cannot use the otherwise far safer option ast.literal_eval() in this case.
You can use eval:
FinalAnswer= eval('Answer1' + Difficulty + 'Answer2')
but this is dangerous if the strings come from user input.
Alternatively, you could do something like that:
FinalAnswer = { '-': Answer1 - Answer2,
'+': Answer1 + Answer2,
'*': Answer1 * Answer2 } [Difficulty]
Depending on how you have your program structured you should just be able to do this with a little bit of control flow.
if difficulty == 1:
operation = '+'
elif difficulty == 2:
operation = '-'
elif difficulty == 3:
operation = '*'
elif difficulty == 4:
operation = '/'

Make python ask questions from strings

I want to make python ask questions to the user - from random variables in lists.
It needs to ask the question requiring an input from the user.
This is my code so far:
import time
import random
question = "0"
score = "0"
name = input("What is your full name?")
print ("Hello " + name, "welcome to The Arithmetic Quiz")
time.sleep(2)
numbers = list(range(1, 50))
operators = ["+", "-", "*"]
numbers1 = list(range(1,10))
print(str(random.choice(numbers)) + random.choice(operators) + str(random.choice(numbers1)))`
How would I make the last line of code ask a question and get an input from the user?
Also how would I make it so that python says whether this is correct when I do not know what python will ask?
The answer is already in your code.
user_input = input(str(random.choice(numbers)) + random.choice(operators) + str(random.choice(numbers)) + "? ") should work.
It gets a sample random number from numbers, gets a random operator from operators, gets another random number from numbers, and stores the input to the variable user_input.
To get Python to check your answer, store the randomly generated arguments inside variables and check them. (If there is a better way of doing this, I would appreciate it if someone pointed it out to me).
operand1 = random.choice(numbers)
operand2 = random.choice(numbers)
operator = random.choice(operators)
if operator == '+':
answer = operand1 + operand2
elif operator == '-':
answer = operand1 - operand2
else:
answer = operand1 * operand2
user_input = input(str(operand1) + operator + str(operand2) + "? ")
if str(answer) == user_input:
print('Correct!')
else:
print('Wrong!')
EDIT: #mhawke's answer has a better way of storing and manipulating the operands. Instead of storing the operators in a list, store them in a dict and map them to their corresponding operator function as so:
import operator
operators = {"+": operator.add, "-": operator.sub, "*": operator.mul}
operand1 = random.choice(numbers)
operand2 = random.choice(numbers)
op = random.choice(operators)
expected_answer = op(operand1, operand2)
Documentation for operator.
For the second part of your question, how to determine whether the user entered the correct answer, you can store the randomly selected values and evaluate the resulting expression. Then compare that to the user's value:
import operator
operators = {"+": operator.add, "-": operator.sub, "*": operator.mul}
operand1 = random.choice(numbers)
operand2 = random.choice(numbers1)
op = random.choice(operators)
expected_answer = op(operand1, operand2)
user_answer = input('{} {} {} = ?: '.format(operand1, op, operand2)
if int(user_answer) == expected_answer:
print('Correct!')
else:
print('Wrong. The correct answer is {}'.format(expected_answer)
The operators are stored in a dictionary. The operator tokens (+, -, *) are the keys in this dictionary, and the values are functions from the operator module that perform the operations. Using a dictionary like this is very flexible because if you wanted to support a new operator, e.g. division, you can just add it to the operators dictionary:
operators = {"+": operator.add, "-": operator.sub, "*": operator.mul, '/': operators.div}

How do i remove letters in a tuple without changing to a string

Long story short, I am making code for random sums, and have taken to using the operator import in order to make it easier and more efficient. However, when printing the result of this:
from operator import add, sub, mul
ops = (add, sub, mul)
op = random.choice(ops)
print("What is",ranNum1,op,ranNum2,"?")
I get:
What is 9 < built-in function sub > 3 ?
I have tried to remove the letters in the result, but it is a tupple, not a string, so this is not possible. Any suggestions?
You can use __name__ to get the name but this will not be the symbolic operator:
>>> print("What is", ranNum1, op.__name__, ranNum2, "?")
What is 6 add 9 ?
>>> print("Answer:", op(ranNum1, ranNum2))
Answer: 15
Adding a dictionary allows you to print the symbolic operator so replace ops with a dictionary:
>>> ops = {add: '+', mul: '*', sub: '-'}
>>> op = random.choice(list(ops))
>>> print("What is", ranNum1, ops[op], ranNum2, "?")
What is 6 + 9 ?
from operator import add, sub, mul
import random
ranNum1 = random.randint(0, 100)
ranNum2 = random.randint(0, 100)
ops = {'+': add, '-': sub, '*': mul}
op = random.choice(list(ops.keys()))
while True:
user_input = int(input('What is {0} {1} {2}?'.format(ranNum1, op, ranNum2)))
if user_input == ops.get(op)(ranNum1, ranNum2):
break
print('Incorrent!')
print('Correct!')

Categories

Resources