IndexError in Quiz program - python

I am having some problems creating a quiz for my son for his revision. It is a quiz which reads a text file, and displays questions in a random order. The quiz stops when he has answered every question twice.
So he can time himself, how would I add a timer in there which starts when the first question is displayed, and prints when he has answered every question correctly twice? I am using python 3.3.
Here is the code so far:
import random
import time
#open the text file
myfile = open("james.txt")
mylines = myfile.read().splitlines()
wrong = 0
#make blank lists
questions = []
answers = []
scores = []
#Seperate the file into Question and answer
for linenumber in range(0, len(mylines), 2):
questions.append(mylines[linenumber])
answers.append(mylines[linenumber+1])
scores.append(0)
#Ask Question
for questionnumber in range(0,len(questions)):
while scores[questionnumber] <2:
questions.append(mylines[linenumber])
questionnumber = random.randint(0,len(questions))
print(questions[questionnumber])
print(scores)
#Generate Possible Answer
possibleanswers = []
possibleanswers.append(answers[questionnumber])
for answerposition in range(1,3):
randomnum = random.randint(0,len(answers)-1)
while answers[randomnum] in possibleanswers:
randomnum = random.randint(0,len(answers)-1)
possibleanswers.append(answers[randomnum])
#Shuffle Answers
random.shuffle(possibleanswers)
for answernumber in range(0,len(possibleanswers)):
print(answernumber+1,possibleanswers[answernumber])
input1 = int(input())
givenanswer = possibleanswers[input1-1]
if givenanswer == answers[questionnumber]:
print("Yes")
scores[questionnumber] = scores[questionnumber]+1
else:
print("No, the answer was",questionnumber)
wrong = wrong+1

questionnumber = random.randint(0,len(questions))
randint is inclusive, so it can return any number up to and including len(questions). If it returns the largest possible number, then you'll get an IndexError. For instance, if questions is three elements long, then questions[3] will be out of range.
Reduce the allowable range of your random numbers:
questionnumber = random.randint(0,len(questions)-1)
Edit: there also appears to be a typo in your #ask question loop, that causes questions to grow larger than answers.
for questionnumber in range(0,len(questions)):
while scores[questionnumber] <2:
questions.append(mylines[linenumber])
# ^^^ this line
This appears to be a copy-paste mistake. It doesn't make much sense to append to questions here, since it should already be fully populated after the #Seperate code. I suggest removing this line.

Related

A way to assign the elements of one list to another list?

Essentially what im trying to do with this code is a quiz. I've made 2 lists, one with the questions another with the answers. I'm not exactly sure if theres a way to check the index of the randomly chosen question with the index of the where the answer is.
here are the two lists and the most relevant code to what im trying here.
questions = ["What is an example of a topology?: ", "What is the best topology for a large network?: ", "What does the '#' do in python?: ", "What is the '%' of this operator in python?: ","What is the most efficient searching algorithm?: ","What is a LAN?: "]
answers = ["Mesh","Star","Comment","Modulus", "Merge","Local Area Network"]
while play == True:
question = choice(questions)
print(question)
x = (questions.index(question))
y =
answer = input(" ")
As you can probably tell, i got a little confused with comparing the index of the question to the answer, so stopped there and looked for help. Any ideas?
You can choose a random index and then use it to get your question/answer:
index = choice(range(len(questions)))
question = questions[index]
answer = answers[index]
You could also use random.randint (instead of random.choice):
index = randint(0, len(questions) - 1)
random.randrange is another option:
index = randrange(len(questions))
I would approach this first by combining the answers and questions to one nested list for simplicity, But I will post for you both scenarios.
First combine the lists
quiz_list = [[i, x] for i,x in zip(questions,answers)]
Then run your while loop
while True:
question = random.choice(quiz_list)
print(question[0])
user_answer = input("Your Answer:")
if user_answer.lower() == question[1].lower():
print("Congratulations! You got it right")
else:
print("Wrong Answer! Try again")
If you want to run with both lists use the index assuming they will not shuffle or sort for whatever reason.
while True:
question = random.choice(questions)
print(question)
user_answer = input("Your Answer:")
if user_answer.lower() == answers[questions.index(question)].lower():
print("Congratulations! You got it right")
else:
print("Wrong Answer! Try again")
questions.index(question) Returns the index of the question
Note: I convert both the user answer and list answer to lowercase for better comparison.
Just use zip to link questions and answers and form a Question Bank:
...
qbank = list(zip(questions, answers))
while play == True:
question, correct_answer = choice(qbank)
input_answer = input(" ")
...
The qbank obj will be a list of tuples of form (question, answer), so the multiple assignment in the loop is just doing a random choice from this list, and giving you the question answer pair. You can then compare the correct_answer with the input_answer to see if the user got it right.

Inconsistent Python outcomes

So I'm having this problem in which my code is inconsistently failing at random times, this has been answered before:(Python 3.7.3 Inconsistent code for song guessing code, stops working at random times now I have had to add a leaderboard to this song guessing game I am doing. I randomly choose a number of which is used to find the artist and song. If right, it will remove the song and artist to prevent dupes and carry on. Here is the code:
loop = 10
attempts = 0
ArtCount = len(artist)
for x in range (ArtCount):
print(ArtCount)
randNum = int(random.randint(0, ArtCount - 1))
randArt = artist[randNum]
ArtInd = artist.index(randArt)# catches element position
songSel = songs[randNum]
print (randNum)
print ("The artist is " + randArt)
time.sleep(0.5)
songie = songSel
print( "The songs first letter be " + songSel[0])
time.sleep(0.5)
print("")
question = input("What song do you believe it to be? ")
if question == (songSel):
songs.remove(songSel)
artist.remove(randArt)
print ("Correct")
print ("Next Question")
if attempts ==0:
points = points + 5
print("+5 Points")
print("")
if question != (songSel):
loop = loop + 1
attempts = attempts + 1
print("")
print("Wrong,", attempts, "questions wrong, careful!")
print("")
time.sleep(0.5)
if attempts == 5:
break
print("GAME OVER")
Pardon my mess, I'm just starting off in making large code, will clean up when finished. I've had the additional problem of having the count controlled loop as 10 (the amount of questions) then having to go pas the loop when you get a question wrong, I've tried having it loop by the amount of songs in the list and I've also tried making a variable that +1 when you get it wrong so you have space to answer but that doesn't work either. After implementing the leaderboard it now doesn't remove any songs (I was messing with the indentation to make the leaderboard print every time.) The error I randomly get is;
randArt = artist[randNum]
IndexError: list index out of range
I'm never sure why this is the code that is the problem, I'm not even sure if it's necessary.
Please, don't use
randNum = int(random.randint(0, ArtCount - 1))
You may easily get a random artist by using:
randArt = random.choice(artist)
The problem is your code had modify the artist array length when you remove item on true answer. You need to get the right artist count after you change.
for x in range (ArtCount):
print(ArtCount)
count = len(artist) # get the new length here
randNum = int(random.randint(0, count - 1)) # use the new length here instead of your old ArtCount

How to not print duplicate lines from an external text file?

I am trying to create a multiple choice quiz using python. I have an external .txt file that has 20 questions in and I want it to select 10 random questions from that file, which it currently does. The file has the layout:
1,Who was the first man to walk on the moon?,A.Michael Jackson,B.Buzz Lightyear,C.Neil Armstrong,D.Nobody,C
The problem i'm having is that I don't want it to print the same question twice.
The only way I can think to solve this is to add detail[0], which is the question number, to a list defined in python and then check within that list to make sure that the question number isn't duplicated.
import random
qno = []
def quiz():
i = 0
global score #makes the score variable global so it can be used outside of the function
score=0 #defines the score variable as '0'
for i in range (1,11): #creates a loop that makes the program print 10 questions
quiz=open('space_quiz_test.txt').read().splitlines() #opens the file containing the questions, reads it and then splits the lines to make them seperate entities
question=random.choice(quiz)
detail = question.split(",")
print(detail[0],detail[1],detail[2],detail[3],detail[4],detail[5])
print(" ")
qno.append(detail[0])
print(qno)
if detail[0] in qno is False:
continue
qno.append(detail[0])
print(qno)
elif detail[0] in qno is True:
if detail[0] not in qno == True:
print(detail[0],detail[1],detail[2],detail[3],detail[4],detail[5])
print(" ")
qno.append(detail[0])
print(qno)
while True:
answer=input("Answer: ")
if answer.upper() not in ('A','B','C','D'):
print("Answer not valid, try again")
else:
break
if answer.upper() == detail[6]:
print("Well done, that's correct!")
score=score + 1
print(score)
continue
elif answer.upper() != detail[6]:
print("Incorrect, the correct answer is ",detail[6])
print(score)
continue
quiz()
When I run this code I expect that no question is repeated twice but it always seems to do that, i'm struggling to think of a way to do this. Any help would be grateful, Thank you!
Use this:
questions = random.sample(quiz, 10)
It will select a random sublist of length 10, from the quiz list.
Also:
You should read the file, and make the question list outside the loop, then just loop over the questions:
with open('space_quiz_test.txt') as f:
quiz = f.readlines()
questions = random.sample(quiz, 10)
for question in questions:
...
Read all the questions:
with open('space_quiz_test.txt') as f:
quiz = f.readlines()
Shuffle the list of questions in place:
random.shuffle(quiz)
Loop on the shuffled list:
for question in quiz:
print(question)
This is because random.choice can give the same output more than once. Instead of using random.choice try
random.shuffle(list) and then choosing the first 10 records from the shuffled list.
quiz=open('space_quiz_test.txt').read().splitlines()
random.shuffle(quiz)
for question in quiz[1:11]:
detail = question.split(",")
print(detail[0],detail[1],detail[2],detail[3],detail[4],detail[5])
You can accomplish this by drawing the questions all at once with choice without replacement, then iterating over those.
import numpy as np
quiz=open('space_quiz_test.txt').read().splitlines() #opens the file containing the questions, reads it and then splits the lines to make them seperate entities
questions=np.random.choice(quiz, size=10, replace=False)
for question in quesions: #creates a loop that makes the program print 10 questions
#rest of your code
Instead of opening the file 10 times, get 10 questions from it and loop asking them:
def get_questions(fn, number):
with open(fn) as f:
# remove empty lines and string the \n from it - else you get
# A\n as last split-value - and your comparisons wont work
# because A\n != A
q = [x.strip() for x in f.readlines() if x.strip()]
random.shuffle(q)
return q[:number]
def quiz():
i = 0
global score # makes the score variable global so it can be used outside of the function
score=0 # defines the score variable as '0'
q = get_questions('space_quiz_test.txt', 10) # gets 10 random questions
for question in q:
detail = question.split(",")
print(detail[0],detail[1],detail[2],detail[3],detail[4],detail[5])
print(" ")
# etc ....
Doku:
inplace list shuffling: random.shuffle
There are several other things to fix:
# global score # not needed, simply return the score from quiz():
my_score = quiz() # now my_score holds the score that you returned in quiz()
...
# logic errors - but that part can be deleted anyway:
elif detail[0] in qno is True: # why `is True`? `elif detail[0] in qno:` is enough
if detail[0] not in qno == True: # you just made sure that `detail[0]` is in it
...
while True:
answer=input("Answer: ").upper() # make it upper once here
if answer not in ('A','B','C','D'): # and remove the .upper() downstream
print("Answer not valid, try again")
else:
break

Displaying the number of questions the user inputs

Currently in the process of making a True or False quiz. Would anyone be kind enough to help me out with the code? As I am unable to display the amount of questions the user wants to answer. The questions are all arranged in an array however, I am having trouble with it.
For example:
-There are 20 questions and the quiz asks the user for how many questions they want to answer
-User enters 5 questions
-Quiz displays 5 random questions out of the 20 in the list
Thank you in advance!
questionlist = [" "]
answerslist=[" "]
score = 0
questions = 0
while True :
questions = int(input("How many questions do you want to answer today? "))
if questions <= len(questionslist) :
break
print("I only have ", len(questions_list), " in my database")
while len(questionslist) > 0 :
I need help after this please
Using python 2.7:
import random
questions_answers = {"Question1?":"answer1","Question2?":"answer2","Question3?":"answer3","Question4?":"answer4","Question5?":"answer5"}
score = 0
while True :
questions = int(raw_input("How many questions do you want to answer today? "))
if questions == 0:
break
if questions > len(questions_answers) :
print("I only have {} in my database".format(len(questions_answers)))
break
for i in range(1, questions+1):
rand_item = random.choice(questions_answers.keys())
print(rand_item)
answer = raw_input("Enter your answer:")
if answer == questions_answers[rand_item]:
print("Correct")
score+=1
else:
print("Wrong")
print ("Your score is {} out of {}".format(score, questions))
Break this problem into steps, then focus on the code for each separate part.
I would retrieve the user input for how many questions he/she desires and create a loop which retrieves questions from this hash map at random for the requested number of questions! In order to retrieve the questions at random you should use a random generator that will return a number between 0 and 1. You should then multiply this number by the length of the quiz and cast this number to an integer. This will then be the index to your array. You must then store the question number in another array and check to see if this question was already asked the next time a random question was picked.
In psuedo code form:
number_of_questions = retrieve_user_input()
questions_asked_thus_far = [] //empty array
question_number = 1
while (question_number<=number_of_questions):
question_number = int(random_number_generator * quiz_array.length)
if question_number is not in questions_asked_thus_ far
questions_asked_thus_far.append(question_number)
question_number ++
print question_number

Python, Explain def function and scoring system? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Can someone explain this piece of code to allow me to understand def functions better, i need to know how the code below acts as a counter and adds up the score at the end of the test,:
for i in range(questions): #ask 10 questions
if quiz():
score +=1
this code was for a test I created, if it can be explained thanks alot, also can someone maybe give an alternative version of this piece of code, the whole code is below :
import random
import math
import operator as op
name = input("What is your name? ")
print("Hi {}! Welcome to the Arithmetic quiz...".format(name))
score = 0
questions = 10
def quiz():
x = random.randint(1, 10)
y = random.randint(1, 10)
ops = {'+': op.add,'-': op.sub,'*': op.mul}
keys = list(ops.keys())
opt = random.choice(keys)
operation = ops[opt]
answer = operation(x, y)
print ("What is {} {} {}?".format(x, opt, y)) #prints the question
user_answer= int(input("Your answer: ")) #prompts users answer
if user_answer != answer: #validate users answer to correct answer
print ("Incorrect. The right answer is",answer"")
return False
else:
print("Correct!")
return True
for i in range(questions): #ask 10 questions
if quiz():
score +=1 #counter
print("{}: You got {}/{} questions correct.".format(name, score, questions,))#'question' if (score==1) else 'questions'
thanks <3
i need to know how the code at the top of the page allows a counter to add up all the correct answers in the quiz
Formatting matters in Python, so take care:
for i in range(questions): #ask 10 questions
if quiz():
score +=1
quiz() gets called 10 times, and returns True if a question was answered correctly. In this case, the variable score will be incremented.
The quiz function asks a single question, takes the user's input, checks it and prints a message accordingly. It is defined in the block of code following def quiz(): and it is called (run) with quiz(). It also returns the value True if the answer was correct or False if it was incorrect.
So, every time it is called, its return value is checked and if it's True (if quiz(): is equivalent to if quiz() == True:), the counter score is incremented.
In fact, you can add True (which actually equals 1) and False (==0) to an integer, so your code (note the indenting):
for i in range(questions): #ask 10 questions
if quiz():
score +=1
could be written:
for i in range(questions): #ask 10 questions
score += quiz()

Categories

Resources