Simple technology quiz

This is my first program that uses more than just boring ol' if/else statements - I made a whole 246 line game that's still a work in progress simply using if/else - and I'm going to email this to my teacher later tonight.

Please suggest more things I can add and report any bugs (although I've found none so far).

# Starting points value
points = 0

# correct() calls this
def correct():
global points
points = points + 1
print("Correct!")
print("You have",points,"points!")
a = input()

# incorrect() calls this
def incorrect():
print("Incorrect!")
ab = input()

print("Welcome to this five question general IT quiz!")
print("If you're stuck and need help, type 'Hint'!")
a = input()

# Question 1

print("Question one:")
q1 = input("What does LAN stand for?")

if q1 == "Hint":
print("The N stands for network...")
q1 = input("What does LAN stand for?")

elif q1 == "hint":
print("The N stands for network...")
q1 = input("What does LAN stand for?")

if q1 == "Local Area Network":
correct()

elif q1 == "local area network":
correct()

elif q1 == "Local area network":
correct()

elif q1 == "Local area Network":
correct()

else:
incorrect()

# Question 2

print("Question 2:")
print("Fill in the blank.")
q2 = input("A monitor is an example of an ------ device.")

if q2 == "Hint":
print("Another example would be speakers or headphones.")
q2 = input("A monitor is an example of an ------ device.")

elif q2 == "hint":
print("Another example would be speakers or headphones.")
q2 = input("A monitor is an example of an ------ device.")

if q2 == "Output":
correct()

elif q2 == "output":
correct()

else:
incorrect()

# Question 3

print("Question 3:")
q3 = input("True or false: To connect to the internet, you MUST have an ethernet cable connected from your router to your PC.")

if q3 == "Hint":
print("Remember, there are two types of internet connecttion.")
q3 = input("True or false: To connect to the internet, you MUST have an ethernet cable connected from your router to your PC.")

elif q3 == "hint":
print("Remember, there are two types of internet connecttion.")
q3 = input("True or false: To connect to the internet, you MUST have an ethernet cable connected from your router to your PC.")

if q3 == "False":
correct()

elif q3 == "false":
correct()

else:
incorrect()

# Question 4

print("Question 4:")
q4 = input("What is the processor made by Intel that is used in PCs designed for networking/server hosting?")

if q4 == "Hint":
print("Begins with an X!")
q4 = input("What is the processor made by Intel that is used in PCs designed for networking/server hosting?")

elif q4 == "hint":
print("Begins with an X!")
q4 = input("What is the processor made by Intel that is used in PCs designed for networking/server hosting?")

if q4 == "Xeon":
correct()

elif q4 == "xeon":
correct()

else:
incorrect()

# Final Question

print("Final question:")
q5 = input("Radeon, EVGA, XFX and Sapphire are companies that make what computer component?")

if q5 == "Hint":
print("A better one of these will boost grapical performance and framerate in games.")
q5 = input("Radeon, EVGA, XFX and Sapphire are companies that make what computer component?")

elif q5 == "hint":
print("A better one of these will boost grapical performance and framerate in games.")
q5 = input("Radeon, EVGA, XFX and Sapphire are companies that make what computer component?")

if q5 == "graphics cards":
correct()

elif q5 == "Graphics Cards":
correct()

elif q5 == "GPUs":
correct()

elif q5 == "gpus":
correct()

elif q5 == "graphics card":
correct()

elif q5 == "Graphics Card":
correct()

elif q5 == "gpu":
correct()

elif q5 == "GPU":
correct()

else:
incorrect()

# End of the quiz

print("The quiz is over! You scored",points,"points!")

if points >= 4:
print("Pretty good!")

if points == 3:

if points == 2:
print("Meh.")

if points < 2:
print("Boo! Try again!")

b = input()

First, you can't possibly check for all possible uppercase/lowercase combinations of the answers, and it is looking messy even as it currently is. This is the perfect place to convert the input to lowercase like this:

q1 = input("What does LAN stand for?").lower()

Now, all you need to do is check for "hint" and "local area network" for question one:

if q1 == "hint":
print("The N stands for network...")
q1 = input("What does LAN stand for?").lower()

if q1 == "local area network":
correct()

else:
incorrect()

In question five, you have multiple inputs. Why don't you handle it like this instead of having multiple if/elif/else statements?

if q5 == "hint":
print("A better one of these will boost grapical performance and framerate in games.")
q5 = input("Radeon, EVGA, XFX and Sapphire are companies that make what computer component?").lower()

if s in ['gpu', 'gpus', 'graphics card', 'graphics cards']:
correct()

else:
incorrect()

In this print call, you should put spaces around your string literals and variables to make it easier to read:

print("You have",points,"points!")

q1 isn't a very descriptive variable name, and it does not hold the question, as it suggests. Also, why are you using one variable name for each question? This code can be cleaned up a lot by creating a method to administer the questions:

while True:

print(hint)
correct()
return
else:
incorrect()
return

Now, the user can input "hint" as many times as they wish.

This is called as:

administer_question("Radeon, EVGA, XFX and Sapphire are companies that make what computer component?",
["gpu", "gpus", "graphics card", "graphics cards"],
"A better one of these will boost graphical performance and frame rate in games.")

I would pass a string to the incorrect() function to display the correct answer to the user:

print("Incorrect!")
pause = input()

Note also that I renamed the variable ab to pause so it demonstrates better that the program is just waiting for the user to input a value to continue. However, with all these pauses for input, maybe you should explain that to the user so they don't wait for the program to respond and wonder what is going on.

• Maybe it's abut outside the OP's original scope, but how do you feel about a "Question" class with a "administer," "correct," and "incorrect" methods? To me it seems like a natural extension of this logic, but I'm hardly an expert programmer myself Mar 22 '15 at 8:33
• @ssdecontrol I don't think that would be a bad idea. However, I'm no expert at Python, and I didn't even remember it had classes. However, it might be a bit much if the OP is only using if/else blocks still.
– user34073
Mar 22 '15 at 17:08

A very easy way to improve your code is to remove near duplicate code.

For instance:

if a == 'A String':
do something
elif a == 'a string':
do something

can be easily compressed to

if a.lower() == 'a string':
do something

If you want to test for many different answers, you can put all the answers in an array and then do something like this:

do something

That will help clean up your GPU question code.

Also, towards the end you have a chain of prints based on point values. This can be compressed by putting all your messages into an array and figuring out the right index.

The simpler code would be:

messages = ["Boo! Try again!", "Boo! Try again!", "Meh.", "Not bad...", "Pretty Good!"]
message_index = max(len(messages) - 1, points)
print(messages[message_index])

This approach also allows you to add new messages in to the array without changing the code.

Repetition

I see this pattern throughout your code:

if q1 == "Local Area Network":
correct()

elif q1 == "local area network":
correct()

elif q1 == "Local area network":
correct()

elif q1 == "Local area Network":
correct()

else:
incorrect()

So basically you are just checking for each possible capitalization of the phrase. But what if I typed:

LOCAL AREA NETWORK

It would output incorrect, even though it is actually correct. Why don't you convert the input to either lower case or upper case, and just check against that? That would take care of any and all correctly spelled cases. Example:

if q1.lower() == "local area network":
correct()

Or...

if q1.upper() == "LOCAL AREA NETWORK":
correct()

Naming

is difficult. What's worst is figuring out what names mean when you're the next person having to maintain the code. A few keystrokes when you write the code can save a lot of headaches for the next person. Example, instead of:

q1 = input("What does LAN stand for?")

Perhaps:

techQuizQuestion1 = input("What does LAN stand for?")

Also, the following variables are problematic because they are not mentioned in the code outside of the declaration, and their names say nothing about them:

a = input()
# ...
b = input()

If they are needed, it's better to give them a meaningful name.

Building off of the other answers, you should use probably casefold instead of lower for caseless comparison. Since this comes up so much, I bit the bullet and wrote something about it on Stack Overflow (You don't have to worry about anything complicated so you can ignore the stuff about unicode normalization.)

One thing you should avoid is global: instead pass in inputs and get out outputs:

points = correct(points)

where correct increments its local points and returns the updated value. This may seem like a bit of a pointless hassle, but it becomes invaluable as you build up and things like classes prevent complexity from being too large an issue.

You should also have everything in main and then call main directly:

def utility_function():
...

def utility_function():
...

def main():
...

main()

That last call to main can also be wrapped as

# Only call if run directly (as opposed to it being imported)
if __name__ == "__main__":
main()

but this is a more minor aspect of code cleanliness given that you aren't going to be using this as a library.

I do not know python well enough to show examples.

Fill in the blank questions will always require a human to check those marked wrong. As you find incorrectly answers marked wrong, you can tweak the code

I developed this technique for submitted answers from a web page and adapted to your interactive input. When answers are submitted from a web page the score for many questions can be scored in a few milliseconds. So fast there is no perceptible delay in the user getting the results.

if x= 1 is much quicker than if x = 'some string expression'

if else should be avoided when possible which in many instances can be done with arrays

create question answer, correction and score arrays
this is for two questions one with true (1) or false (0) and one with 4 multiple choice answers.

The arrays are made to evaluate to zero on wrong and one on correct.
The arrays for output, incorrect on zero and correct on one. Or pad the array so the answers are 1,2.. rather than 0,1...

Where q is the question number and a is number of the answer chosen.
From multiple choice you just use an array with more elements [1,0,0,0], the marks array remains the same. questions[ Is the answer 1. True or 0. False','Is the answer 1. points = [0,1][1,0] or if you don't want zero as a choice:

initializations:

points = [0,0,1][0,1,0,0,0]
response= [' WRONG: The correct answer is ','CORRECT ']

quiz:
convert the a from a = input to an integer if necessary

while True:
a = input(question[q])
score += points[q][a]
mark = print(response[points[q][a]],answers[points[q][a]],' score =  ',score)

This also eliminates the calling of a subroutine correct() and incorrect().

This is how I scored the answers to a personality survey:
The code is in PHP but the concept is clear.
Total time expended is less than a millisecond or two, lightning fast.

foreach ($_POST as$key => $a) { if substr($key,0,1) != 'q'){continue;}
$q = intval(substr($key,1));
$score +=$points[$q][$a];
}

While the arrays may appear to be a lot of overhead, the processing is so much more efficient.
When the arrays are local and somewhat small the data is in L1 cache of the microprocessor.

The L1 cache of an Intel i7 is 32KB Data and 32KB instruction. If the data is less than 32KB then it will reside in L1 cache.

Data access should be grouped together. Data writes should be segregated from data fetch. Data access should be segregated from computational code.

Processor branch prediction is an important consideration for efficiency.

In my code I use the structure

if( condition ){continue;}

Rather than the less efficient:

if (condition){
continue;
}
else{
...
}

the true condition should usually precede the false. so if I used the if else` this would be better:

if (most true conditions){
...
}
else{
continue;
}

The point: Branching, as in if else, is very inefficient.

It helps to understand how the micro-processor's microcode and instruction execution blocks function. All programmers should be familiar with Intel's 64 and IA-32 Architectures Optimization Reference Manual at this link:

This is mostly for compiler programmers but there are many optimizations for other programmers in their "User/Source Coding Rules"

The most important Source coding rules pertain to Branching (if else), Loops (while), and variable declaration and organization.

You don't have to read all 642 pages. At a minimum read Chapter 3

Chapter 3 General Optimization Guidelines

And read the User/Source Coding Rules, search the document using this search phrase: "User/Source Coding Rule".