I am making a maths test where each question will be either adding, multiplying or subtracting randomly chosen numbers. My operator will be chosen at random, however I cannot work out how to calculate with the operator. My problem is here:
answer = input()
if answer ==(number1,operator,number2):
print('Correct')
How can I make it so the operator is used in a calculation. For example, if the random numbers were two and five, and the random operator was '+', how would I code my program so that it would end up actually doing the calculation and getting an answer, so in this case it would be:
answer =input()
if answer == 10:
print('Correct')
Basically, how can I do a calculation to check to see if the answer is actually correct?
My full code is below.
import random
score = 0 #score of user
questions = 0 #number of questions asked
operator = ["+","-","*"]
number1 = random.randint(1,20)
number2 = random.randint(1,20)
print("You have now reached the next level!This is a test of your addition and subtraction")
print("You will now be asked ten random questions")
while questions<10: #while I have asked less than ten questions
operator = random.choice(operator)
question = '{} {} {}'.format(number1, operator, number2)
print("What is " + str(number1) +str(operator) +str(number2), "?")
answer = input()
if answer ==(number1,operator,number2):
print("You are correct")
score =score+1
else:
print("incorrect")
Sorry if I have been unclear, thanks in advance
Use functions in a dictionary:
operator_functions = {
'+': lambda a, b: a + b,
'-': lambda a, b: a - b,
'*': lambda a, b: a * b,
'/': lambda a, b: a / b,
}
Now you can map an operator in a string to a function:
operator_functions[operator](number1, number2)
There are even ready-made functions for this is the operator module:
import operator
operator_functions = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv,
}
Note that you need to be careful about using variable names! You used operator first to create a list of operators, then also use it to store the one operator you picked with random.choice(), replacing the list:
operator = random.choice(operator)
Use separate names here:
operators = ["+","-","*"]
# ...
picked_operator = random.choice(operators)
You are looking for the eval function. eval will take a string with math operators and compute the answer. In your final if statement check it like this...
if answer == eval(question):
import operator
import random
operators = {
"+": operator.add,
"-": operator.sub,
"/": operator.truediv,
"*": operator.mul
}
y = float(input("Enter number: "))
z = float(input("Enter number: "))
x = random.choice(operators.keys())
print (operators[x](y, z))
Use the operator lib, creating a dict with operators as keys and the methods as values.
from operator import add, mul, sub
import random
score = 0 # score of user
questions = 0 # number of questions asked
operators = {"+": add, "-": sub, "*": mul}
print("You have now reached the next level!This is a test of your addition and subtraction")
print("You will now be asked ten random questions")
# create list of dict keys to pass to random.choice
keys = list(operators)
# use range
for _ in range(10):
number1 = random.randint(1, 20)
number2 = random.randint(1, 20)
operator = random.choice(keys)
# cast answer to int, operators[operator]will be either add, mul or sub
# which we then call on number1 and number2
answer = int(input("What is {} {} {}?".format(number1,operator, number2)))
if answer == (operators[operator](number1, number2)):
print("You are correct")
score += 1
else:
print("incorrect")
You need to cast answer to int a string could never be equal to an int.
In the code random.choice(keys) will pick one of the three dicts keys * - or +, we do a lookup on the dict with operators[operator] i.e operators["*"] returns mul we can then call mul(n1,n2) on the two random numbers.
You also need to move the number1 = random.randint(1, 20).. inside the while loop or you will end up asking the same questions and you can pass the string to input, you don't need to print.
For your specific case, instead of making the dictionary, I would just create a list of tuples with the operator string representation and the operator builtin function:
import operator
import random
operators = [('+', operator.add), ('-', operator.sub), ('*', operator.mul)]
for i in range(10):
a = random.randint(1, 20)
b = random.randint(1, 20)
op, fn = random.choice(operators)
print("{} {} {} = {}".format(a, op, b, fn(a, b)))
14 * 4 = 56
6 + 12 = 18
11 + 11 = 22
7 - 9 = -2
9 - 4 = 5
17 * 5 = 85
19 - 13 = 6
9 - 4 = 5
20 * 20 = 400
5 * 3 = 15
Random.choice on your list will return a tuple that you can unpack into the operator str representation and the function that you can call.
import operator
import random
score = 0
operators = [('+', operator.add), ('-', operator.sub), ('*', operator.mul)]
for i in range(10):
a = random.randint(1, 20)
b = random.randint(1, 20)
op, fn = random.choice(operators)
prompt = "What is {} {} {}?\n".format(a, op, b)
if int(input(prompt)) == fn(a, b):
score += 1
print("You are correct")
else:
print("incorrect")
print("Score: {}".format(score))
Related
i'm quite new at Python and I wondered how to make a calculator that i can add, subtract, multiply, divide and other operators on more than two numbers . I would be thankful if you gave me an explanation. I'm questioning because I have in my mind an awful and inefficient method of doing this , that being adding more elif tags for more operators and more numbers
TL:DR (i guess) :
i thinked about making a calculator made with python that has options for more operator and numbers ( but i don't know how to make a simpler one :
i.e.:30 + 30 * 30.
67.874 / 20.
69 + 69 + 69 + 69 + 69 + 69.
30 ** ( i think this is a power operator ) 2.
etc.
I can help you if you didin't understand what i want , you can question me
this is my normal calculator without input of more than two numbers and one operator
def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y
def divide(x, y):
return x / y
num1 = float(input("Enter a number :"))
op = input("Enter your selected operator :")
num2 = float(input("Enter another number :"))
if op == "+":
print(num1, "+", num2, "=", add(num1, num2))
elif op == "-":
print(num1, "-", num2, "=", subtract(num1, num2))
elif op == "*":
print(num1, "*", num2, "=", multiply(num1, num2))
elif op == "/":
print(num1, "/", num2, "=", divide(num1, num2))
else:
print("Invalid input")
I know this comment/answer code isn't having indenting , but stack woudn't let me post with indenting and the file itself does have indenting so idk
result = None
operand = None
operator = None
wait_for_number = True
while True:
if operator == '=':
print(f"Result: {result}")
break
elif wait_for_number == True:
while True:
try:
operand = float(input("Enter number: "))
except ValueError:
print("Oops! It is not a number. Try again.")
else:
if result == None:
result = operand
else:
if operator == '+':
result = result + operand
elif operator == '-':
result = result - operand
elif operator == '*':
result = result * operand
elif operator == '/':
result = result / operand
break
wait_for_number = False
else:
while True:
operator = input("Enter one of operators +, -, *, /, =: ")
if operator in ('+', '-', '*', '/', '='):
break
else:
print("Oops! It is not a valid operator. Try again.")
wait_for_number = True
your question isn’t clear enough, but if I got it right than this should work. Important to note: using the eval() function is not a good practice since it can be really dangerous if the inputs are not coming from you. Here are some of the dangers of it: https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
The code:
# the function takes an operator as a string like: “*” and multiple numbers thanks to the * (args) operator.
def calculate(operator, *numbers):
result = numbers[0]
#the for cycle goes through all numbers except the first
for number in range(1, len(numbers)):
#the eval() function makes it possible to python to interpret strings as a code part
result = eval(f"{result} {operator} {str(numbers[i])}")
print(result)
Here is the code without eval().
import operator
# the function takes an operator as a string like: “*” and multiple numbers thanks to the * (args) operator.
def calculate(op, *numbers):
# binding each operator to its string counterpart
operators = {
"+": operator.add,
"-": operator.sub,
"*": operator.mul,
"/": operator.truediv
}
result = numbers[0]
#the for cycle goes through all numbers except the first
for number in range(1, len(numbers)):
# carrying out the operation, using the dictionary above
result = operators[op](result, numbers[number])
print(result)
Recently I created a 24 game solver with python
Read this website if you do not know what the 24 game is:
https://www.pagat.com/adders/24.html
Here is the code:
from itertools import permutations, product, chain, zip_longest
from fractions import Fraction as F
solutions = []
def ask4():
num1 = input("Enter First Number: ")
num2 = input("Enter Second Number: ")
num3 = input("Enter Third Number: ")
num4 = input("Enter Fourth Number: ")
digits = [num1, num2, num3, num4]
return list(digits)
def solve(digits, solutions):
digit_length = len(digits)
expr_length = 2 * digit_length - 1
digit_perm = sorted(set(permutations(digits)))
op_comb = list(product('+-*/', repeat=digit_length-1))
brackets = ([()] + [(x,y)
for x in range(0, expr_length, 2)
for y in range(x+4, expr_length+2, 2)
if (x,y) != (0,expr_length+1)]
+ [(0, 3+1, 4+2, 7+3)])
for d in digit_perm:
for ops in op_comb:
if '/' in ops:
d2 = [('F(%s)' % i) for i in d]
else:
d2 = d
ex = list(chain.from_iterable(zip_longest(d2, ops, fillvalue='')))
for b in brackets:
exp = ex[::]
for insert_point, bracket in zip(b, '()'*(len(b)//2)):
exp.insert(insert_point, bracket)
txt = ''.join(exp)
try:
num = eval(txt)
except ZeroDivisionError:
continue
if num == 24:
if '/' in ops:
exp = [(term if not term.startswith('F(') else term[2])
for term in exp]
ans = ' '.join(exp).rstrip()
print("Solution found:", ans)
solutions.extend(ans)
return ans
print("No solution found for:", ' '.join(digits))
def main():
digits = ask4()
solve(digits, solutions)
print(len(solutions))
print("Bye")
main()
Right now, my code only shows one solution for the numbers given, even when there are clearly more solutions.
So if someone knows how to do this please help me
Thanks
You're not allowing the code to finish it's task before all of the solutions have been calculated and listed. Better to save the solutions in a list/array instead of returning it straight away.
Your function is returning as soon as it finds a solution. Delete the return statement. After the loop, you can return the list of all solutions if desired. To check if there were none, see if the length of the list is zero (so you know when to say there are no solutions).
I would also suggest making solutions local to solve, instead of global.
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}
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!')
My task is to create a maths quiz for primary school children. this is what I have done so far:
import random
import math
def test():
num1=random.randint(1, 10)
num2=random.randint(1, 10)
ops = ['+', '-', '*']
operation = random.choice(ops)
num3=int(eval(str(num1) + operation + str(num2)))
print ("What is {} {} {}?".format(num1, operation, num2))
userAnswer= int(input("Your answer:"))
if userAnswer != num3:
print ("Incorrect. The right answer is {}".format(num3))
return False
else:
print ("correct")
return True
username=input("What is your name?")
print ("Welcome "+username+" to the Arithmetic quiz")
correctAnswers=0
for question_number in range(10):
if test():
correctAnswers +=1
print("{}: You got {} answers correct".format(username, correctAnswers))
What I now need to do is make my program only create questions with positive answers. e.g nothing like 3-10=-7
I've tried searching everywhere online but I cant find anything so I've turned to you guys for help. Any help will be appreciated :)
What I would recommend is:
#Random code...
if num1<num2:
num1, num2 = num2, num1
#Rest of program
So that 3 - 7 = -4 becomes 7 - 3 = 4
The reason I recommend doing this is that the answer would still be the same as the previous equation, just positive instead of negative, so you are still testing the same numbers.
Keep the larger number on the left of the expression, also use operator instead of eval:
from operator import add, sub, mul
def test():
num1 = random.randint(1, 10)
num2 = random.randint(1, 10)
d = {"+": add, "-": sub, "*": mul}
operation = random.choice(list(d)))
num1 = max(num1, num2)
num2 = min(num1, num2)
num3 = d[operation](num1, num2)
print("What is {} {} {}?".format(num1, operation, num2))
userAnswer = int(input("Your answer:"))
if userAnswer != num3:
print("Incorrect. The right answer is {}".format(num3))
return False
else:
print("correct")
return True
username = input("What is your name?")
print("Welcome {} to the Arithmetic quiz".format(username))
correctAnswers = sum(test() for question_number in range(10))
print("{}: You got {} answers correct".format(username, correctAnswers))
Or as #jonclements suggests sorting will also work:
num2, num1 = sorted([num1, num2])
On another note you should really be using a try/except to verify the user input and cast to an int otherwise the first value that cannot be cast to an int your program will crash.
You can choose the numbers such that num2 will be between 1 and num1 like:
num1=random.randint(1, 10)
num2=random.randint(1, num1)
or that num1 > num2:
n1=random.randint(1, 10)
n2=random.randint(1, 10)
num1 = max(n1,n2)
num2 = min(n1,n2)
i would go with the first option. no extra variables, no extra lines.
after the code that chooses the random numbers you can add this while loop:
while num3<0:
num1=random.randint(1, 10)
num2=random.randint(1, 10)
ops = ['+','-','*']
operation = random.choice(ops)
num3=int(eval(str(num1) + operation + str(num2)))
It will enter this loop every time the answer is negative. This will ensure that the answer is positive when the program quits the loop.
A change in one line should do it:
if num1 > num2:
num3=int(eval(str(num1) + operation + str(num2)))
else:
num3=int(eval(str(num2) + operation + str(num1)))