Trying to fit the spirit of your question, and to flesh out the comments saying it's unnecesary (it is), I nerfed your script so it always reads '20' from the user (which is sometimes correct) and just builds the output strings but doesn't print them, so I could run it through the timeit
module.
Start: 20,000 runs in ~1.47 seconds.
from random import choice, randint
to make them local names for faster lookup, same with re.match
, improvement ~0.04 seconds over the 20,000 runs.
- Move the ops list creation outside the loop, ~0.03s
- Changing the regex to match "[^0-9-]" instead, ~0.07s
- Not computing str(product) twice, ~0.01s
- Changing the nested while condition to
while not userans.isdigit():
, which is probably good enough for positive whole number answers, ~0.31s
- Whoops subtraction might mean negative answers, so that isn't quite right. Could replace with this but it's fine for now - not invoking regexes is the biggest step performance gain.
- Calculate the product before asking the user for their input, so there's less work going on between reading their input and knowing the answer, ~unknown, might shorten the give answer-get response gap.
- Tweak the way the calculations are done and checked, a touch slower, but less code repetition so it's shorter, as asked, but it's also uglier and harder to read.
Finish: 20,000 runs in ~0.996 seconds.
Result: 1/3rd faster! Hooray! If my version is 100%, yours is 150%. If my version is harder to read, well so be it.
from random import randint, choice
from re import match
score = 0
i = 1
ops = ["-","+","*"]
ops2 = {"-":sub,"+":add,"*":mul}
while i < 11:
num1, num2, operation, userans = randint(1,4),randint(5,12),choice(ops),"",
q = (str(num1) + operation + str(num2) + ": ")
product = str(ops2[operation](num1, num2))
while not userans.isdigit():
userans = input(q)
if userans == product:
print("you are correct!")
score = score + 1
else:
print("You are incorrect! The correct answer was " + product)
print("Your score is " + str(score))
i=i+1
but
we're talking 0.5 seconds faster over 20,000 runs. 0.000025 seconds per 10 question run. 0.0000025 seconds faster per question/answer.
With random numbers involved, this is pretty much measurement noise. This tiny amounts of change could be significantly affected by different versions of the Python runtime doing slightly different things internally.
2.5 micro seconds, is it? Oft quoted figures say humans feel things are "instant" at around 10-100 milliseconds.
Your code is already way way way fast enough not cause it to feel laggy.
If it feels laggy, it's probably a network involved - running the code on a remote computer over SSH or Remote Desktop, or over the internet in a web browser. Or it's a broken terminal client or web based terminal which struggles with basic text input/output.
Instead, fix it a bit for readability - like counting from 1 to less-than-11 as a way to loop ten times. Change the "*" to "+" in the regex and lose the "userans = """ check, cut out some of the str() going on, don't call it "product" when it could be a sum or a difference.
from random import randint, choice
import re
score = 0
operations = ["-", "+", "*"]
for turn in range(10):
num1 = randint(1,4)
num2 = randint(5,12)
operation = choice(operations)
q = "{0} {1} {2}: ".format(num1, operation, num2)
userans = ""
while not re.match('^[0-9-]+$', userans):
userans = input(q)
if operation == '+':
result = num1 + num2
elif operation == '-':
result = num1 - num2
elif operation == '*':
result = num1 * num2
result = str(result)
if result == userans:
print ("you are correct!")
score = score + 1
else:
print("You are incorrect! The correct answer was " + product)
print ("Your score is " + str(score))