-4
import random, re
score = 0
i = 1
while i < 11:
    ops = ["-","+","*"]
    num1, num2, operation, userans = random.randint(1,4),random.randint(5,12),random.choice(ops),"",
    q = (str(num1) + operation + str(num2) + ":   ")
    while userans == "" or not re.match(r'^[0-9-]*$', userans):
     userans = input(q)

    if operation == '+':
        product = num1+num2 
    elif operation == '-':
        product = num1-num2
    elif operation == '*':
        product = num1*num2

    if str(product) == userans:
        print ("you are correct!")
        score = score + 1
    else:
        print("You are incorrect! The correct answer was " + str(product))

    print ("Your score is " + str(score))
    i=i+1

This is the code I have but I need it to be less laggy. Also the program is a random question generator

  • 10
    There is nothing slow about this code; the only thing that is slow is the user entering input. – Martijn Pieters Sep 23 '15 at 21:04
  • 1
    If you're using an online interpreter or something like that, it can be painfully slow as it takes forever to import some modules. – Dleep Sep 23 '15 at 21:19
  • 1
    What do you have in mind as a bar for **not slow**. How fast can you type? – Shawn Mehan Sep 23 '15 at 21:20
  • 4
    Long code does not imply slow code (on your title). – Fernando Matsumoto Sep 23 '15 at 21:21
  • @MartijnPieters: it may be slow if the answers are provided by another program. Though given `num1`, `num2` range, even brute-force would be instantaneous here. If we were to increase the range significantly then performance issues might arise e.g., [`str(long)` is quadratic in CPython](http://stackoverflow.com/a/28480239/4279) – jfs Sep 23 '15 at 21:52

1 Answers1

2

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))
Community
  • 1
  • 1
TessellatingHeckler
  • 27,511
  • 4
  • 48
  • 87