# Math equation generator program

I am building this program in Python to generate 10 random arithmetic questions of either multiplication, addition or subtraction and then saves users scores to a .txt file. I just wanted some help condensing the code as I'm really stuck as of what to do with it.

How can I combine the function (e.g. multiplication, addition and subtraction) into one?

import random
import time
import sys

ans = 0   #variable to hold question answer
question = 0   #question number
user_score = 0  #user's score
userInput = int()   #where user enters the answer
lastName = str()   #holds last name
firstName = str()   #holds first name
form = str()    #holds user's form

def function(score,name):   #writes user's information to a .txt file
sumOfStudent = (name + ' scored ' + str(user_score))
classNameTxt = (className, '.txt.')
f = open(className, 'a')
f.write(sumOfStudent + form + '\n')
f.close()

def multiplication():   #creates a multiplication question
global ans
numberOne, numberTwo  = random.randint(0,20), random.randint(0,20)
print("What is" , numberOne , "*" , numberTwo)
ans = (numberOne * numberTwo)

def subtraction():   #creates a subtraction question
global ans
numberOne, numberTwo  = random.randint(0,20), random.randint(0,20)
print("What is" , numberOne , "-" , numberTwo)
ans = (numberOne - numberTwo)

global ans
numberOne, numberTwo  = random.randint(0,20), random.randint(0,20)
print("What is" , numberOne , "+" , numberTwo)
ans = (numberOne + numberTwo)

operation = [multiplication,subtraction,addition]   #holds all of the opperators
randOperation = random.choice(operation)    #chooses a random operator

lastName = input("Please enter your surname: ").title()
firstName = input("Please enter your first name: ").title()
className = input("Please enter your form: ").title()
print()

def main():   #main game loop - ask questions and checks it against answer, stops are a give amount of questions
question = 0
user_score = 0
randOperation = random.choice(operation)

while True:
try:
randOperation()
randOperation = random.choice(operation)
if question >= 10:
break
userInput = int(input("Enter the answer: "))
if userInput == ans:
print("Correct!" + "\n")
user_score += 1
question += 1
else:
print("Incorrect!" + "\n")
question += 1
except ValueError:
print("I'm sorry that's invalid")
question += 1

main()    #initializes the function

print(firstName, lastName , "you scored" , user_score , "out of 10")   #shows the user's score and name

user_name = firstName + ' ' + lastName
function(user_score,user_name)

while True:
try:
options = int(input('''Press '1' to view users' scores,
press '2' to restart the test,
press '3' to exit the game,

Enter option here: '''))
except ValueError:
print("I'm sorry that was invalid...")

if options == 3:  #exits the game...
sys.exit()

elif options == 2:   #starts the game loop again because it's in a function
main()

elif options == 1:   #displays everything on the .txt file
f = open('userScore.txt', 'r')
print()

else:
print("Sorry, I don't understand. Please try again...")
print()



Besides the obvious code repetition that you mentioned, a few salient issues deserve mentioning:

• Your main() function is not really the main code of your program. Rather, you have some free-floating code outside of any function, and the main function is actually called endMenu(), which is surprising.
• The endMenu() function is improperly recursive. The while True loop should suffice.
• You use global variables a lot. While firstName and lastName are somewhat excusable (they are entered once by the user, and never change subsequently), you really shouldn't use globals for transient state like ans, question, etc.
• function is the least-informative name possible for a function.

To address those issues, as well as the code repetition you mentioned, I'd write the program like this:

import operator
import random

OPERATIONS = [
('-', operator.sub),
('*', operator.mul),
]

def random_question(binary_operations, operand_range):
"""Generate a pair consisting of a random question (as a string)
and its answer (as a number)"""
op_sym, op_func = random.choice(binary_operations)
n1 = random.randint(min(operand_range), max(operand_range))
n2 = random.randint(min(operand_range), max(operand_range))
question = '{} {} {}'.format(n1, op_sym, n2)
answer = op_func(n1, n2)

def quiz(number_of_questions):
"""Ask the specified number of questions, and return the number of correct
score = 0
for _ in range(number_of_questions):
question, answer = random_question(OPERATIONS, range(0, 21))
print('What is {}'.format(question))
try:
user_input = float(input("Enter the answer: "))
except ValueError:
print("I'm sorry that's invalid")
else:
if answer == user_input:
print("Correct!\n")
score += 1
else:
print("Incorrect!\n")
return score

def identify_user():
# TODO, as an exercise for you
pass

def display_score(first_name, last_name, class_name):
# TODO, as an exercise for you
pass

# TODO, as an exercise for you
pass

def main():
first_name, last_name, class_name = identify_user()
while True:
if menu_choice == 1:        # Display score
display_score(first_name, last_name, class_name)

elif menu_choice == 2:      # Run quiz
QUESTIONS = 10
score = quiz(QUESTIONS)
print('{first_name} {last_name}, you scored {score} out of {QUESTIONS}'.format(**locals()))

elif menu_choice == 3:      # Exit
break

else:
print("Sorry, I don't understand. Please try again...")
print()

if __name__ == '__main__':
main()


Observe how there are no global variables: each function accepts parameters and returns specific output values.

Don't initialize variables like this:

userInput = int()
lastName = str()
firstName = str()
form = str()


This is equivalent and better:

userInput = 0
lastName = ''
firstName = ''
form = ''


When opening files, use with:

with open('userScore.txt', 'r') as f: