Basic Python Struggles - python

I'm making a maths skills testing program and was wondering if there's a way in which i can make random questions appear in my program instead of having to do this every single time;
import time
start = time.time()
userinput = input("\nWhat is 11+7?")
if userinput=="18":
print("\nNot bad, lets try something a little harder...")
print('It took you {0:0.1f} seconds to answer the
question'.format(time.time() - start))
else:
print("\nAt least you got one right")
print('It took you {0:0.1f} seconds to answer the
question'.format(time.time() - start))
exit()
Also, how can i add a while statement into this? I would also like to add a def function in if possible. Thanks.

Choose a random operator and random numbers:
import operator
import random
ops = {'+': operator.add,
'-': operator.sub} # add mul and div if you wish
keys_tuple = tuple(ops.keys())
num_a = random.randint(1, 10) # use larger range if you wish
num_b = random.randint(1, 10) # use larger range if you wish
op = random.choice(keys_tuple)
print('{}{}{}=?'.format(num_a, op, num_b))
expected_answer = ops[op](num_a, num_b)
user_answer = int(input())
if user_answer == expected_answer:
print('Correct')
else:
print('Wrong')
As for the while, simple wrap the whole code in a while True loop that breaks if the user inputs a certain value (ie 'quit', which will currently raise a ValueError)

This is almost entirely #DeepSpace's code, but to answer your question of how to add the while loop, just throw all of the code after the initial definitions into the scope of a while loop:
import operator
import random
ops = {'+': operator.add,
'-': operator.sub} # add mul and div if you wish
keys_tuple = tuple(ops.keys())
while True:
num_a = random.randint(1, 10) # use larger range if you wish
num_b = random.randint(1, 10) # use larger range if you wish
op = random.choice(keys_tuple)
print('{}{}{}=?'.format(num_a, op, num_b))
expected_answer = ops[op](num_a, num_b)
user_answer = int(input())
if user_answer == expected_answer:
print('Correct')
else:
print('Wrong')

So you want to make math problems basically? Here is what you need to do for that:
Make two random ints - step 1
See if the answer adds up to the answer - step 2
You can now try solving it yourself. In case you need some help, you can come back and see this:
from random import randint
def get_random_int(): # Function to get random int
random_num = randint(1, 20) #Gets an int between 1 and 20. Change if needed
return random_num
def check_answer(first_number, second_number, input_ans): # function to check answer correction
if (first_number + second_number == input_ans):
return "Correct answer!"
else:
return "Try again!"
number_1 = get_random_int()
number_2 = get_random_int()
user_input = input("What is %s plus %s?" % ( str(number_1), str(number_2) ))
# Wrap in str() to display as string
print( check_answer(number_1, number_2, int(user_input) ) )
# Wrap in int() because it is a number
And if you need this to loop constantly, wrap this in a while True: endless loop. Be sure to give a way to exit from it! (Use break in the code to exit from loop)
Hope this helps :)

Related

How do I implement a timer on each question asked in a quiz?

I was attempting to create a quiz and one of the criteria is to limit the time available to solve for each question in the quiz. I looked up certain tutorials but some require an input of x seconds for the timer to go off while others looked more like a stopwatch...
I was wondering how do I do like a background timer that ticks down as soon as the question is printed out and skips to the next question if, for example the 30-second period has ended? I'm clueless in the timer function and was having problems to even try to implement them onto my codes. Could someone give out a few pointers so I can sorta progress further in implementing a working timer?
Thank you!
EDITED section below:
The timer that I want to implement onto my coding:
import time
import threading
def atimer():
print("Time's up.")
a_timer = threading.Timer(10.0, atimer)
a_timer.start()
print("")
This is the whole coding that I tried to implement the timer into.
I noticed that when I tried to define qtimer to just print 1 or 2 lines of statements the timer works but I want the timer to stop and go to second question or stop and give the user another attempt to retry the question, so I tried to attach a bunch of codes after the definition and it didn't work. I know I'm most probably doing something wrong here since I'm not quite familiar with time or threading functions. Is there a workaround?
def qtimer():
print("I'm sorry but your time is up for this question.")
print("You may have another attempt if you wish to, with reduced marks allocated.")
response1 = input("Type 'Yes' for another attempt, anything else to skip: ")
if response1 == "Yes":
Answ = input("Which option would you go for this time?: ")
Answ = int(Answ)
if possible[Answ - 1] == qaItem.corrAnsw:
print("Your answer was correct.")
corr += 1
marks += 0.5 * qaItem.diff
else:
print("Your answer was wrong.")
print("Correct answer was: " + qaItem.corrAnsw)
print("Explanation: " + qaItem.expl)
print("")
else:
print("Correct answer was: " + qaItem.corrAnsw)
print("Explanation: " + qaItem.expl)
print("")
class A:
def __init__(self, question, correctAnswer, otherAnswers, difficulty, explanation):
self.question = question
self.corrAnsw = correctAnswer
self.otherAnsw = otherAnswers
self.diff = difficulty
self.expl = explanation
qaList = [A("What is COVID-19?", "Coronavirus Disease 2019", ["Wuhan virus", "I don't understand...", "Coronavirus Disease v19"], 1, "Explanation 1"),
A("What describes COVID-19?", "A disease", ["A virus", "A parasite", "A bacteriophage"], 1, "Explanation 2"),
A("What causes COVID-19?", "SARS-CoV-2", ["Coronavirus", "Mimivirus", "Rubeola Virus"], 1, "Explanation 3"),
A("Which of the following is used in COVID-19 treatment?", "Lopinavir / Ritonavir ", ["Midazolam / Triazolam", "Amiodarone", "Phenytoin"], 2, "Explanation 4"),
A("Which of the following receptors is used by COVID-19 to infect human cells?", "ACE-2 Receptors", ["ApoE4 Receptors", "TCR Receptors", "CD28 Receptors"], 3, "Explanation 5")]
corr = 0
marks = 0
random.shuffle(qaList)
for qaItem in qaList:
q_timer = threading.Timer(5.0, qtimer)
q_timer.start()
print(qaItem.question)
print("Possible answers are:")
possible = qaItem.otherAnsw + [qaItem.corrAnsw]
random.shuffle(possible)
count = 0
while count < len(possible):
print(str(count+1) + ": " + possible[count])
count += 1
print("Please enter the number of your answer:")
Answ = input()
Answ = str(Answ)
while not Answ.isdigit():
print("That was not a number. Please enter the number of your answer:")
Answ = input()
Answ = int(Answ)
Answ = int(Answ)
while Answ > 4 or Answ < 1:
print("That number doesn't correspond to any answer. Please enter the number of your answer:")
Answ = input()
Answ = int(Answ)
if possible[Answ-1] == qaItem.corrAnsw:
print("Your answer was correct.")
corr += 1
marks += 1 * qaItem.diff
else:
print("Your answer was wrong.")
response = input("Would you want to try again? If so, input 'Yes' to attempt it again, if not just input whatever!")
if response == "Yes":
Answ = input("Which option would you go for this time?: ")
Answ = int(Answ)
if possible[Answ - 1] == qaItem.corrAnsw:
print("Your answer was correct.")
corr += 1
marks += 0.5 * qaItem.diff
else:
print("Your answer was wrong.")
print("Correct answer was: " + qaItem.corrAnsw)
print("Explanation: " + qaItem.expl)
print("")
else:
print("Correct answer was: " + qaItem.corrAnsw)
print("Explanation: " + qaItem.expl)
print("")
print("You answered " + str(corr) + " of " + str(len(qaList)) + " questions correctly.")
print("You have achieved a total score of " + str(marks) + ".")
Even with a timer, the main thread can't proceed past waiting for the user to input a number; so if the user doesn't nothing, the timer function runs, and once it has finished the main thread is still waiting for input at
print("Please enter the number of your answer:")
Answ = input()
You could have a global flag that the timer thread sets to tell the main thread to treat the input received as response1 in the timer code, and also have a flag to tell the timer that an answer was received, and so on, and it quickly becomes rather complicated.
So rather than trying to work around the blocking call to input by communicating between the timer and main thread, take the non-blocking input example from https://stackoverflow.com/a/22085679/1527 and stop the loop early if the time is up.
def timed_input(msg, timeout=10):
kb = KBHit()
print(msg)
end_time = time.time() + timeout
warn_time = 5
result = None
while True:
if kb.kbhit():
c = kb.getch()
if '0' <= c <= '9':
result = int(c)
break
print(c)
if time.time() > end_time:
print('time is up')
break
if time.time() > end_time - warn_time:
print(f'{warn_time}s left')
warn_time = warn_time - 1
kb.set_normal_term()
return result
# Test
if __name__ == "__main__":
result = timed_input('Enter a number between 1 and 4')
if result is None:
print('be quicker next time')
elif 1 <= result <= 4:
print('ok')
else:
print(f'{result} is not between 1 and 4')
Note also that breaking up into smaller functions helps make the code easier to follow, the logic of the test doesn't need to know about the logic of the timeout.

I don't understand why my indentation is wrong, and when I input an answer it doesn't output anything, other than an error

I'm running this using PyScripter w/ Python 2.7.6. I don't understand why my code is wrong. Could someone give me an explanation?
def mainMenu():
answer = input("""Main Menu:
Pythagoras
Repeat Program
Quit""")
if answer == "Pythagoras":
pythagoras()
elif answer == "Repeat Program":
mainMenu()
elif answer == "Quit":
print("Program ended")
else:
mainMenu()
def pythagoras():
if answer == "Pythagoras":
aNotSquared = input("Input the value of A")
bNotSquared = input("Input the value of B")
aSquared = aNotSquared ** 2
bSquared = bNotSquared ** 2
valueC = aSquared + bSquared
print(valueC)
mainMenu()
Not sure if indentation errors occured when pasting over but outside that are a couple things to fix as well
Already test if answer == 'Pythagoras' before entering the pythagoras() function, doesn't work nor make sense to check answer inside the function
Cannot perform math on strings need to convert your input to int
General formatting for clarity, when taking inputs and printing result
PEP-8 snake_case not CamelCase
Slightly Improved Version:
from math import sqrt
def main_menu():
answer = input("""Main Menu:
Pythagoras
Repeat Program
Quit\nChoose option from above: """)
if answer == "Pythagoras":
pythagoras()
elif answer == "Repeat Program":
main_menu()
elif answer == "Quit":
print("Program ended")
else:
main_menu()
def pythagoras():
a_not_sqr = int(input("Input the value of A: "))
b_not_sqr = int(input("Input the value of B: "))
a_sqr = a_not_sqr ** 2
b_sqr = b_not_sqr ** 2
c_sqr = a_sqr + b_sqr
c_not_sqr = sqrt(c_sqr)
print(f'C Squared = {c_sqr}')
print(f'C = {round(c_not_sqr, 2)}')
main_menu()
Main Menu:
Pythagoras
Repeat Program
Quit
Choose option from above: Pythagoras
Input the value of A: 10
Input the value of B: 10
C Squared = 200
C = 14.14

How to re-run code [duplicate]

This question already has answers here:
Asking the user for input until they give a valid response
(22 answers)
Closed 6 years ago.
I'm trying to figure out how to make Python go back to the top of the code. In SmallBasic, you do
start:
textwindow.writeline("Poo")
goto start
But I can't figure out how you do that in Python :/ Any ideas anyone?
The code I'm trying to loop is this
#Alan's Toolkit for conversions
def start() :
print ("Welcome to the converter toolkit made by Alan.")
op = input ("Please input what operation you wish to perform. 1 for Fahrenheit to Celsius, 2 for meters to centimetres and 3 for megabytes to gigabytes")
if op == "1":
f1 = input ("Please enter your fahrenheit temperature: ")
f1 = int(f1)
a1 = (f1 - 32) / 1.8
a1 = str(a1)
print (a1+" celsius")
elif op == "2":
m1 = input ("Please input your the amount of meters you wish to convert: ")
m1 = int(m1)
m2 = (m1 * 100)
m2 = str(m2)
print (m2+" m")
if op == "3":
mb1 = input ("Please input the amount of megabytes you want to convert")
mb1 = int(mb1)
mb2 = (mb1 / 1024)
mb3 = (mb2 / 1024)
mb3 = str(mb3)
print (mb3+" GB")
else:
print ("Sorry, that was an invalid command!")
start()
So basically, when the user finishes their conversion, I want it to loop back to the top. I still can't put your loop examples into practise with this, as each time I use the def function to loop, it says that "op" is not defined.
Use an infinite loop:
while True:
print('Hello world!')
This certainly can apply to your start() function as well; you can exit the loop with either break, or use return to exit the function altogether, which also terminates the loop:
def start():
print ("Welcome to the converter toolkit made by Alan.")
while True:
op = input ("Please input what operation you wish to perform. 1 for Fahrenheit to Celsius, 2 for meters to centimetres and 3 for megabytes to gigabytes")
if op == "1":
f1 = input ("Please enter your fahrenheit temperature: ")
f1 = int(f1)
a1 = (f1 - 32) / 1.8
a1 = str(a1)
print (a1+" celsius")
elif op == "2":
m1 = input ("Please input your the amount of meters you wish to convert: ")
m1 = int(m1)
m2 = (m1 * 100)
m2 = str(m2)
print (m2+" m")
if op == "3":
mb1 = input ("Please input the amount of megabytes you want to convert")
mb1 = int(mb1)
mb2 = (mb1 / 1024)
mb3 = (mb2 / 1024)
mb3 = str(mb3)
print (mb3+" GB")
else:
print ("Sorry, that was an invalid command!")
If you were to add an option to quit as well, that could be:
if op.lower() in {'q', 'quit', 'e', 'exit'}:
print("Goodbye!")
return
for example.
Python, like most modern programming languages, does not support "goto". Instead, you must use control functions. There are essentially two ways to do this.
1. Loops
An example of how you could do exactly what your SmallBasic example does is as follows:
while True :
print "Poo"
It's that simple.
2. Recursion
def the_func() :
print "Poo"
the_func()
the_func()
Note on Recursion: Only do this if you have a specific number of times you want to go back to the beginning (in which case add a case when the recursion should stop). It is a bad idea to do an infinite recursion like I define above, because you will eventually run out of memory!
Edited to Answer Question More Specifically
#Alan's Toolkit for conversions
invalid_input = True
def start() :
print ("Welcome to the converter toolkit made by Alan.")
op = input ("Please input what operation you wish to perform. 1 for Fahrenheit to Celsius, 2 for meters to centimetres and 3 for megabytes to gigabytes")
if op == "1":
#stuff
invalid_input = False # Set to False because input was valid
elif op == "2":
#stuff
invalid_input = False # Set to False because input was valid
elif op == "3": # you still have this as "if"; I would recommend keeping it as elif
#stuff
invalid_input = False # Set to False because input was valid
else:
print ("Sorry, that was an invalid command!")
while invalid_input: # this will loop until invalid_input is set to be False
start()
You can easily do it with loops, there are two types of loops
For Loops:
for i in range(0,5):
print 'Hello World'
While Loops:
count = 1
while count <= 5:
print 'Hello World'
count += 1
Each of these loops print "Hello World" five times
Python has control flow statements instead of goto statements. One implementation of control flow is Python's while loop. You can give it a boolean condition (boolean values are either True or False in Python), and the loop will execute repeatedly until that condition becomes false. If you want to loop forever, all you have to do is start an infinite loop.
Be careful if you decide to run the following example code. Press Control+C in your shell while it is running if you ever want to kill the process. Note that the process must be in the foreground for this to work.
while True:
# do stuff here
pass
The line # do stuff here is just a comment. It doesn't execute anything. pass is just a placeholder in python that basically says "Hi, I'm a line of code, but skip me because I don't do anything."
Now let's say you want to repeatedly ask the user for input forever and ever, and only exit the program if the user inputs the character 'q' for quit.
You could do something like this:
while True:
cmd = raw_input('Do you want to quit? Enter \'q\'!')
if cmd == 'q':
break
cmd will just store whatever the user inputs (the user will be prompted to type something and hit enter). If cmd stores just the letter 'q', the code will forcefully break out of its enclosing loop. The break statement lets you escape any kind of loop. Even an infinite one! It is extremely useful to learn if you ever want to program user applications which often run on infinite loops. If the user does not type exactly the letter 'q', the user will just be prompted repeatedly and infinitely until the process is forcefully killed or the user decides that he's had enough of this annoying program and just wants to quit.
write a for or while loop and put all of your code inside of it? Goto type programming is a thing of the past.
https://wiki.python.org/moin/ForLoop
You need to use a while loop. If you make a while loop, and there's no instruction after the loop, it'll become an infinite loop,and won't stop until you manually stop it.
def start():
Offset = 5
def getMode():
while True:
print('Do you wish to encrypt or decrypt a message?')
mode = input().lower()
if mode in 'encrypt e decrypt d'.split():
return mode
else:
print('Please be sensible try just the lower case')
def getMessage():
print('Enter your message wanted to :')
return input()
def getKey():
key = 0
while True:
print('Enter the key number (1-%s)' % (Offset))
key = int(input())
if (key >= 1 and key <= Offset):
return key
def getTranslatedMessage(mode, message, key):
if mode[0] == 'd':
key = -key
translated = ''
for symbol in message:
if symbol.isalpha():
num = ord(symbol)
num += key
if symbol.isupper():
if num > ord('Z'):
num -= 26
elif num < ord('A'):
num += 26
elif symbol.islower():
if num > ord('z'):
num -= 26
elif num < ord('a'):
num += 26
translated += chr(num)
else:
translated += symbol
return translated
mode = getMode()
message = getMessage()
key = getKey()
print('Your translated text is:')
print(getTranslatedMessage(mode, message, key))
if op.lower() in {'q', 'quit', 'e', 'exit'}:
print("Goodbye!")
return

Integer Validation Python

I need to add a validation whilst in a while loop.
However when I use this validation it doesn't work and instead only comes up with the error message saying I haven't used a base 10/an integer when I want it to come up with the validation error message and let the user try again.
I don't know if having it in a while loop makes the validation I use any different, does it?
Also do I need to change this "def inputNumber(message):" to what my input is stored as?
And this "userInput = int(input(message))" to what my input is stored as?
import time
import random
question = 0
score = 0
name = input("What is your full name?")
print ("Hello " + name, "welcome to The Arithmetic Quiz. Use integers to enter the answer!")
time.sleep(2)
operands1 = list(range(2, 12))
operators = ["+","-","x"]
operands2 = list(range(2, 12))
while question < 10:
operand1 = random.choice(operands1)
operand2 = random.choice(operands2)
operator = random.choice(operators)
def inputNumber(message):
while True:
try:
userInput = int(input(message))
except ValueError:
print("Not an integer! Try again.")
continue
else:
return userInput
break
user_answer =int(input('{} {} {} = '.format(operand1, operator, operand2)))
I doubt you want to have your function definitions within a while loop like you're doing here:
while question < 10:
...
def inputNumber(message):
...
Instead, you can define the function outside the loop and call it x number of times from a loop elsewhere. E.g.
def inputNumber(message):
...
return userInput
while question < 10:
# pick random numbers/operators
...
# call inputNumber() with numbers/operators as message. Return user_answer
user_answer = int(inputNumber('{} {} {} = '.format(operand1, operator, operand2)))
# check if the answer is correct
...
# increment question so it doesn't run infinitely
question += 1
#user6104134 has already solved this problem; however, I'd like to provide an answer for anyone else having similar issues.
Try this solution
import random
import time
question = 0
score = 0
def inputnumber(prompt):
while True:
response = raw_input(prompt)
try:
if isinstance(response, int):
return int(response)
else:
print "Not an integer! Try again."
except ValueError:
print "Not an integer! Try again."
name = raw_input("What is your full name? ")
print ("Hello " + name, "welcome to The Arithmetic Quiz. Use integers to enter the answer!")
time.sleep(2)
operands1 = list(range(2, 12))
operators = ["+", "-", "x"]
operands2 = list(range(2, 12))
while question < 10:
operand1 = random.choice(operands1)
operand2 = random.choice(operands2)
operator = random.choice(operators)
user_answer = int(inputnumber('{} {} {} = '.format(operand1, operator, operand2)))
question += 1
Issues
First, you should declare function definitions outside of your script and call the function by identifier 'inputNumber()'
Also notice the slight change in Try/Except, and the PEP 8 Style Guide compliant formatting.

Python please tell me if my maths answer is right

I wish to add a feature which tells the user when he/she has answered correctly to the random maths questions that are given.
import random
def answers():
correct_answer_P_ = ((str(difficulty_one + difficulty_one))) #P = PLUS, ADDITION +
correct_answer_M_ = ((str(difficulty_one * difficulty_one))) #M = MULTIPLY *
correct_answer_T_ = ((str(difficulty_one - difficulty_one))) #T = TAKE AWAY, MINUS -
def random_symbols():
symbols = random.choice (["+","-","*"])
return symbols
def difficulty_one():
dif_one = random.randrange (1,10,1)
return dif_one
def questions():
question = (str(difficulty_one())) + random_symbols() + (str(difficulty_one())) + " = "
return question
start = input("press start to begin!: ")
if (start == "start"):
print ("here's ten questions, good luck!")
for questions_num in range(1,11):
print ("Question ",questions_num)
input(questions())
if (random_symbols == "+"):
if (dif_one == correct_answer_P_):
print("correct!")
elif(random_symbols == "-"):
if (dif_one == correct_answer_T_):
print("correct!")
elif(random_symbols == "*"):
if (dif_one == correct_answer_M_):
print("correct!")
else:
print("incorrect!")
I tried this from getting some advice from a friend who said that i needed to create variables for each symbol that would be randomly inserted; the variables should compare the users answer and say its correct but it skips all the if statements and goes straight to saying its incorrect.
Any suggestions? Don't be harsh if I'm doing something dumb because I've just started python at the moment.
Quick note the part in this code has been cut out of my original to make it simple for people to see what I'm trying to do.
There's a way easier way of implementing this. Try this instead:
import operator
questions = [(1,2), (4,2), (8,1), (10,100)] # operands for your questions
operators = {"+" : operator.add,
"-" : operator.sub,
"*" : operator.mul}
# a dictionary containing each operator's symbol and the resulting function
# (operator.add(x,y) is equivalent to x+y)
for num, operands in enumerate(questions,start=1):
# iterate through each set of operands, enumerating starting at 1
operator = random.choice(operators)
# return a random symbol from operators
answer = operators[operator](*operands)
# operators[operator] is the function, which we then call with the operands
q_text = "{} {} {} = ?".format(str(operands[0]), operator, str(operands[1]))
print("Question {}".format(str(num)))
print(q_text)
user_answer = input(">>")
if float(user_answer) == answer:
# correct!
else:
# fail!

Categories

Resources