Posts: 16 Threads: 6 Joined: May 2020 I have Python 3.10, and want to read a series of multiple choice or Yes-No/True-False test questions into a list (or array or whatever) from an Excel spreadsheet, complete with 5 possible answers for the multiple choice questions and, of course, 2 possible answers for the true/false or yes/no questions. Each question has a preferred answer priority, 1st or best answer, 2nd best answer… worst or 5th best answer, etc. The program should first show how many questions there are to choose from, and the user chooses how many questions they want to answer. Can someone show me how to randomly choose the questions to ask (no repeats), as well as randomly shuffle the answers (while keeping track of their priority (i.e. 1st or best choice, 2nd best, etc.)? Seems like a nightmare for this novice Python programmer. Many thanks in advance, Perplexed in Pittsburgh Posts: 453 Threads: 16 Joined: Jun 2022 Sep-26-2022, 08:02 PM (This post was last modified: Sep-27-2022, 11:51 AM by rob101.) I've not covered the 'Excel' part of this, as I'm not a Excel user, but from what I do know, I can't see that part being a huge challenge: I see the QandA dictionary being built, in part, from your Excel file, with which I'm sure OPs will be able to help, if needs be. This is one way that one could begin to build the Q&A part: from random import shuffle, randint answered = 'answered' answer = 'answer' question = 'question' answers = 'answers' QandA = { 1:{ answered: False, answer: '', question: "This will be the text for question 1.", # place holder answers: ("Answer 1", "Answer 2", "Answer 3", "Answer 4", "Answer 5") # place holder }, 2:{ answered: False, answer: '', question: "This will be the text for question 2.", # place holder answers: ("Answer 1", "Answer 2", "Answer 3", "Answer 4", "Answer 5") # place holder }, 3:{ answered: False, answer: '', question: "This will be the text for question 3.", # place holder answers: ("Answer 1", "Answer 2", "Answer 3", "Answer 4", "Answer 5") # place holder }, 4:{ answered: False, answer: '', question: "This will be the text for question 4.", # place holder answers: ("Answer 1", "Answer 2", "Answer 3", "Answer 4", "Answer 5") # place holder }, 5:{ answered: False, answer: '', question: "This will be the text for question 5.", # place holder answers: ("True", "False") # place holder } } # the driver no_of_qs = len(QandA) print(f"There will be {no_of_qs} questions.\n") q_asked = [] #holds the index of the question asked q = 0 done = False while not done: q = randint(1,no_of_qs) if len(q_asked) < no_of_qs: if q not in q_asked: q_asked.append(q) ask = QandA[q][question] print(ask) options = [option for option in range(0,len(QandA[q][answers]))] if len(options) > 2: # no need to shuffle True/False shuffle(options) for choose, ans in enumerate(options,1): print(f"{choose}: {QandA[q][answers][ans]}") the_answer = False while not the_answer: the_answer = input(f"\n1 to {len(options)} or 0 to pass.\n> ") if len(the_answer) > 1 or the_answer.isalpha() or int(the_answer)not in range(0,len(options)+1): the_answer = False print("Invalid answer.") if the_answer != '0': QandA[q][answered] = True QandA[q][answer] = QandA[q][answers][options[int(the_answer)-1]] print() else: done = True for q in range(1,no_of_qs+1): if QandA[q][answered]: print(f"Question {q} was answered: {QandA[q][answer]}.") else: print(f"Question {q} was not answered.")Not too sure if this is going to be of any help, or if anyone else has a better way for this to be done. I've also not covered the binary part of this (questions that have a simple yes/no answer), but I don't see why that could not be implemented in some way; I'll have a look at that next, if you're still interested in moving this forward. Code update: Some minor changes, just to make for a better base solution... Added a True/False option and also a feedback for the questions that have been answered, from which a score could be calculated, based on whatever system you choose. Sig: >>> import this The UNIX philosophy: "Do one thing, and do it well." "The danger of computers becoming like humans is not as great as the danger of humans becoming like computers." :~ Konrad Zuse "Everything should be made as simple as possible, but not simpler." :~ Albert Einstein Posts: 6,920 Threads: 22 Joined: Feb 2020 Sep-27-2022, 04:23 PM (This post was last modified: Sep-27-2022, 04:23 PM by deanhystad.) I'd bet Excel really means csv. After loading the csv file (or maybe the Excel file) the trickiest part will be formatting the question. For True/False the choices should be "T" and "F". for Yes/No the choices should be "Y" and "N". For multiple choice the choices can be anything. Letters, numbers, first unique letter in each choice, etc. I like letters because they are easier for me to type. For kids, numbers is probably a better choice. For random, either use random.sample() or random.shuffle(). Both are guaranteed to not repeat. This is a rough example. I have no idea how to handle "2nd best answer" because I have no idea what is meant by "2nd best answer" in a multiple choice test. Do you get partial credit if you don't pick the "worst" answer? from io import StringIO import csv import random # Standin for CSV file. Question followed by choices. # Imagine "Question 1" is "What was the capital of Germany in 1956?", and it is followed # by "Bonn", "Berlin", "Frankfurt", "Flensburg", "Munich". First choice is correct, but # all choices have been capitals except Munich (the worst choice). file = StringIO( """\ "Question 1","Choice 1","Choice 2","Choice 3","Choice 4","Choice 5" "Question 2","Choice 1","Choice 2","Choice 3","Choice 4" "Question 3","True","False" "Question 4","Choice 1","Choice 2","Choice 3" "Question 5","False","True" "Question 6","Yes","No" "Question 7","No","Yes" """ ) # True/False and Yes/No are special cases and should always be presented # in the same order and use special answer keys. Choices for other questions # appear in random order. TRUE_FALSE = {"T": "True", "F": "False"} YES_NO = {"Y": "Yes", "N": "No"} def get_answer(question, choices): """Get user input. Input must match one of the choice keys""" print(f"\n{question}") for key, value in choices.items(): print(f"{key}: {value}") selection = input("> ").upper() while True: if selection in choices: return choices[selection] selection = input(f"Please choose from {', '.join(choices)}: ").upper() def ask_question(question): """Format question. Randomize choices. Return True if selection is correct""" question, *choices = question if choices[0] in YES_NO.values(): options = YES_NO elif choices[0] in TRUE_FALSE.values(): options = TRUE_FALSE else: # Any multiple choice that is not True/False or Yes/No # Use 1234567 instead of ABCDEFG if want "1: choice" instead of "A: choice" options = { a: b for a, b in zip("ABCDEFG", random.sample(choices, k=len(choices))) } return get_answer(question, options) == choices[0] # First choice is correct # Load and shuffle the questions questions = list(csv.reader(file)) random.shuffle(questions) # Ask questions and keep score score = 0 for question in questions: if ask_question(question): score += 1 print(score) |