Personality Quizzes

Summary of Deliverables

By the end of HW02, here’s what you’ll need to submit to Gradescope:

  • personality_quiz.py
  • readme_quiz.txt
  • my_quiz.quiz

0. Getting started

A. Goals

The goal of this assignment is to familiarize you with lists, iteration, strings, and reading data from a file. The specific goals are to:

  • Learn about file formats & structured data
  • Use nested loops
  • Parse information from strings
  • Use Python command-line arguments

At the end of this assignment, you will produce a program that delivers interactive Personality Quizzes to a user.

B. Background

Personality Quizzes are sets of questions designed to determine how the quiztaker fits into certain categories. Some of these quizzes purport to be serious and scientific, hoping to reveal something essential about a person’s behavior as a result of their personality “types”. Among these (pseudo)scientific groupings, you may have heard of the Myers-Briggs test or the Big Five test.1

Other quizzes are designed to be a bit more lighthearted while telling you about yourself: your Dungeons and Dragons moral alignment or your Hogwarts house are two such examples.2 There are quizzes that are just plain entertaining, helping you identify which beloved character you most resemble. And finally, there are quizzes that, well…

I really don't understand it either.

C. Your program

You are going to write a program that reads in a quiz from another file. This quiz file will contain information about the quiz, its questions, and then the rules for scoring the quiztaker’s answers and showing them the outcome. The Python code that you write will allow you take any quiz file that matches the provided format and present it to the user in this interactive format. We’ve provided two examples of quizzes and you’ll be writing your own, too.

D. First Steps

You should see personality_quiz.py, lila_or_lenu.quiz, and pet.quiz in your Codio filetree. Reach out to course staff if you don’t see these!

If you need to download the original files again, you can find them here.

In order to complete this assignment, you will need to use the following Python skills:

  • Using input() to read input from the user during execution
  • Converting lines (strings) into lists with .split()
  • Converting strings to numeric values using int()
  • Reading command line arguments using sys.argv
  • Reading information from a file object using open() and readline()
  • Using values from one list as indices for positions in another list
  • Finding the position of the smallest value in a list

You can review these skills by referring to the linked resources.

E. Advice

  • Run and debug frequently! Make one small change at a time, ensuring that your program works as you expect it to after each change.
  • You can test your program easily by adding in temporary print() statements. For instance, if you read in a line of text, you can print its value to check that it contains the information that you expect! When you’re done testing & debugging, you should remove these temporary print() statements.
    • If you are not getting the outputs you expect, print out the values of variables at different points in the program (i.e. before a loop, inside the body of a loop, after the loop)
  • Keep your code organized by using indentation and avoiding too many blank lines.
  • Comment frequently (this helps you and others understand the code) and use descriptive variable names.

1. Command Line Arguments

You can review the details of command line arguments in Python by reading these notes.

Your personality_quiz program will take just one command line argument: a string that is the name of the file containing the quiz information. The quiz instructions (questions, titles, scoring details, etc.) are stored in separate text files ending in .quiz so that we can use our program to load different quizzes. Make sure to read the command line argument as the first thing you do and store it in a variable called filename. Recall that command line arguments are stored inside of sys.argv, so your program must start by importing sys.

A. Checkpoint

Try running personality_quiz.py with a few different quiz file names. To make sure that you are reading and capturing the file names properly, print them out. Since you are passing in command line arguments, you must run the program from the terminal and cannot simply use the “Run” button that you may have used on previous assignments. Here are a couple of example executions that you should be able to match at this point, keeping in mind that lines starting with $ represent commands you have to type into the terminal.

$ python personality_quiz.py lila_or_lenu.quiz
lila_or_lenu.quiz
$ python personality_quiz.py my_made_up_quiz_name.quiz
my_made_up_quiz_name.quiz

Your program should not crash. Verify that your program behaves exactly in this way. Make sure to keep this print statement in your program!

2. Printing the Title & Description

Your goal for this part will be to read the title and description from the quiz file and print them out.

A. Quiz File Format: Title & Description

The .quiz files all start in the same way: one line containing the title of the quiz, followed by three lines that contain the description that the quiz taker will see when starting the quiz. These lines will be read verbatim from the file and then printed directly to the user. You can assume that none of these first four lines will be empty.

Quiz Title
Description Line One
Description Line Two
Description Line Three

B. Setting up a File Reader

The Python standard library provides the function open() to allow you to access information from a file within your program.

In your personality_quiz.py program, you can declare a variable called quiz_file and have it store the reading connection to the quiz file like so:

# creates a variable quiz_file to be used to read from the file
quiz_file = open(filename, 'r') 

quiz_file is just a variable name. Technically, you could name this variable anything, but for consistency with the instructions, we recommend that you use this name. Keep in mind that you only need to declare and initialize quiz_file once!

C. Reading values from the file

Now that quiz_file is initialized, you can access/read information from it using quiz_file.readline(). The output of readline() will include the newline character at the end of the str that you receive. For example, if we are running the program on pet.quiz, then the first result of readline() is exactly the following:

"What Household Pet Would You Be?\n"

This newline character, '\n', signifies that this string is an entire line. But if we were to print out that string, Python would print out two new lines after the actual title: one for the '\n' present in the string, and one extra on the end because that’s what print() normally does. We will want to remove this trailing newline character so that the text is printed without a bunch of extra space. The easiest way to do this is by calling .strip() on the lines as you read them.

Read the first four lines of the file and print them out so that the user sees the quiz title and description. You don’t need to store these values in variables anywhere. Remember that reading starts from the top left of the file, and reads left-to-right and then onto the next line below.

D. Checkpoint

You should be able to run your program with these specified command line arguments and see the corresponding outputs printed exactly.

$ python personality_quiz.py lila_or_lenu.quiz
lila_or_lenu.quiz
Are You a Lila or a Lenu?
Lila Cerullo and Lenu Greco are the main characters of Elena Ferrante's Neapolitan Novels.
While they form a remarkable bond of friendship, they are very different people! Take
this quiz to determine whether you're more like Lila or more like Lenu.
$ python personality_quiz.py pet.quiz
pet.quiz
What Household Pet Would You Be?
Maybe you're a cat!
Maybe you're a dog instead.
Maybe you're actually a fish. Let's find out.

3. Questions and Answers

Next, we’ll print the questions and let the quiz taker respond to them. Our goal is to print a question, ask the user for their answer, and save this result. We’ll repeat that process for each question in the file.

A. Quiz File Format: Questions & Answers

The next unread line in the quiz file contains two numbers: the total number of possible outcomes from the quiz and the number of questions in the quiz, respectively. For example, in lila_or_lenu.quiz, this line looks like:

2 3

You can verify that there are two possible outcomes (Lila or Lenu) and three questions. These numbers should always be positive, but there are otherwise no restrictions on them.

The next set of lines contain the questions and answers. There will always be the same number of outcomes as answers per question. For example, since we read on the previous line that there are three questions with two possible outcomes, then the next six lines would look like the following, keeping in mind that we start counting from 0.

Question 0. Question text here
Answer 0
Answer 1
Question 1. Question text here
Answer 0
Answer 1
Question 2. Question text here
Answer 0
Answer 1

Since there are three questions with two outcomes, we have nine question and answer lines to read.

B. Asking and Answering

First, read the number of outcomes and number of questions from the quiz file and make sure to save these values into variables so that we can use them later. For the purposes of these instructions, we’ll call these variables num_outcomes and num_questions, respectively. Both values will be represented as characters in a string, so it will be up to you to parse that information out of the string. It is recommended that you use .split() as a way to transform the string into a list of strings. Then, you can use int() to transform the constituent strings into numeric values that can be used as parameters for counting later.

Then, for each question:

  • read the line containing the question text from the quiz file & print it
  • for each line representing a possible choice:
    • read that possible choice for that question from the quiz file
    • print that possible choice with numbers, starting at 0, followed by a . character.
  • after all answers are read and printed, read the quiz taker’s answer using input(), making sure to remember to parse it as an integer.

You can assume that the user will always give you a value in the valid range—don’t worry about handling malformed answers.

For this checkpoint, you don’t need to save the user’s answers yet. What you want to make sure that you can do is print each of the question & answer groups one at a time, pausing between each group until the quiz taker answers the question.

C. Checkpoint

Run your program on pet.quiz and don’t provide any input after the program starts running. Make sure that your output matches this exactly, and that the program doesn’t stop running!

$ python personality_quiz.py pet.quiz
pet.quiz
What Household Pet Would You Be?
Maybe you're a cat!
Maybe you're a dog instead.
Maybe you're actually a fish. Let's find out.
Question 0. Do you like the outdoors?
0. Not at all.
1. Yes, I love being outside.
2. Yes, but only the beach or the pool.

Then, if you type 1 in the terminal and press enter/return, you should see the following output exactly. (The 1 you see on line 9 is the one you typed, not anything that gets printed by the program.)

pet.quiz
What Household Pet Would You Be?
Maybe you're a cat!
Maybe you're a dog instead.
Maybe you're actually a fish. Let's find out.
Question 0. Do you like the outdoors?
0. Not at all.
1. Yes, I love being outside.
2. Yes, but only the beach or the pool.
1
Question 1. How do you feel about meeting new people?
0. Love it.
1. Hate it.
2. Totally indifferent.

Finally, type in 0 and press enter/return. Your program should stop executing.

D. Recording Answers

In order to figure out what the quiz taker’s final result will be, we’ll have to store all of the answers that they respond. You should initialize an empty list that will be used to store all of the given answers. In this guide, we’ll call that list answers. You can use .append() to add the most recent answer to the end of the list. That way, when the quiz taker gives an answer x to Question y, you will be storing the value x in position y of the answers list.

E. Checkpoint

While we’ll eventually score all of the answers in order to decide what result the quiz taker gets, you should verify that you are correctly storing all of the answers first. Do this by printing out the contents of answers.

Try running python personality_quiz.py lila_or_lenu.py and giving answers 0, 1, and 0. At the end, you should see 0 1 0 get printed! If you provide three different answers, you should see those numbers printed in the same order.

Make sure to delete the print statement for this checkpoint before submitting!

4. Scoring

Now that we have all the answers, we should tally up the results and give the quiz taker the answer they’ve been waiting for!

A. Quiz File Format: Scoring Guide

Next, we find the scoring guide. There will be one line per question, and on each line there will be one number per outcome/answer. The first line in the scoring guide reflects how the answers for the first question will be scored, the second line corresponds to the second question, and so on.

The scoring in the quiz works by associating each answer with one of the possible outcomes. In lila_or_lenu.quiz, the scoring guide looks like so:

0 1
0 1
1 0

This indicates that picking the first answer to Question 0 would award a point to Outcome 0 and that picking the second answer in Question 0 would award a point to Outcome 1. The same pattern follows for Question 1 since the lines are identical. Notice that the third line is different, though: in Question 2, choosing the first answer would award a point to Outcome 1 and the second answer awards a point to Outcome 0.

After the scoring guide, we have the results messages. There will be one line per possible outcome in the quiz, and your job after scoring will be to print out only the line representing the outcome that has accumulated the highest score.

B. Scoring the Answers

At this point, you should declare an list that will store the total points awarded to each potential outcome—we’ll call this list scores. Make sure that the list has the correct size to store one point tally per outcome. Before we start scoring, each outcome’s point tally should start at 0. Once you have the answers list and the scores list, you have everything you need to tally up the results. There are a few ways that you can approach this, but here’s one recommendation:

  • Iterate over each of the answer values stored in answers. For each answer,
    • read the next line of the scoring guide from the file
    • split the scoring guide into an list of strings (e.g. "0 1" becomes ["0", "1"])
    • find the outcome associated with this answer to this question by reading the corresponding value inside of the scoring guide list and transforming it into an int value
    • use the outcome as an index in the scores list to determine which position’s tally to increment by one.

This process can feel a bit complicated—let’s review a short example where the quiz taker provided answers 0, 1 to pet.quiz.

To look up what the quiz taker answered for the first question, we would look at position 0 of the answers list.

This would be the value 0, so then we would look up which outcome gets a point for this answer. We’ll read the first line of the scoring guide—0 1 2—and store these values in a list.

By visiting position 0 of this scoring list, we see that the value stored there is 0. This means that outcome 0 gets a point, so we could navigate to scores[0] and increment the value stored there.

After doing this, we see that outcome 0 has the most points so far. But we still have one more question to score!

For the second question, we look up answers[1], which is 1. So, we figure out which outcome to award a point to by looking up scoring[0], which is 0. We award a point to outcome 0 by incrementing scores[0].

This might be a bit confusing in writing! Don’t panic, you will understand this process. If you’re struggling to get it from reading, please ask for help! This is a great opportunity to ask a TA during Office Hours.

C. Printing the Final Result

Now that you have added up all of the points in the scores list, it’s time to check which outcome got the largest point total. (If multiple outcomes have the same maximum score, then just pick the first one in the list.) There are two ways you can do this:

  1. Iterate through scores in order to find the index with the maximum value.
  2. Think about how some built-in functions like max() and .index() might be able to help you here.

The messages to print for each outcome are located as the last few lines of the file, right after the scoring guide. Once you have the winning outcome, use this to decide which of the final lines to print out. In pet.quiz, if outcome 0 is the winner, then you’d print the first result line ("You're a cat!"). If outcome 2 is the winner, then you’d print out "You're a fish!".

D. Checkpoint

Try running python personality_quiz.py lila_or_lenu.quiz and give the answers 1, 0, 0. This should mean that outcome 1, or “Lenu”, is the outcome that gets the highest number of points. Your final output should then look like this:

$ python personality_quiz.py lila_or_lenu.quiz
lila_or_lenu.quiz
Are You a Lila or a Lenu?
Lila Cerullo and Lenu Greco are the main characters of Elena Ferrante's Neapolitan Novels.
While they form a remarkable bond of friendship, they are very different people! Take
this quiz to determine whether you're more like Lila or more like Lenu.
Question 0. Are you more of an artist or a writer?
0. Artist
1. Writer
1
Question 1. Growing up, were you an only child? If not, were you close with your siblings?
0. Close
1. Not close or only child
0
Question 2. After college, where would you prefer to live?
0. Far away someplace new
1. Close to my hometown
0
You're a Lenu! You might be a bit shy, but you have a ton of talent! You're a person who won't let their past define them.

Then, try running python personality_quiz.py pet.quiz and give answers 2 and 2. This means “fish” wins, and you should see:

$ python personality_quiz.py pet.quiz
pet.quiz
What Household Pet Would You Be?
Maybe you're a cat!
Maybe you're a dog instead.
Maybe you're actually a fish. Let's find out.
Question 0. Do you like the outdoors?
0. Not at all.
1. Yes, I love being outside.
2. Yes, but only the beach or the pool.
2
Question 1. How do you feel about meeting new people?
0. Love it.
1. Hate it.
2. Totally indifferent.
2
You're a fish!

5. Write Your Own Quiz!

This is not just for fun—by writing your own my_quiz.quiz file, you’ll verify your understanding of the file format and get another quiz example that you can use to test your code. When we grade your assignment, we’ll test it on quiz files you haven’t seen before to make sure that your code works on all kinds of examples in the format. You can verify that you’re meeting all the specifications by coming up with a quiz of your own. Plus, it should be fun to write your own quiz.

Things to keep in mind:

  • Make sure to write at least three questions and have at least two possible outcomes. You can include as many questions as you want, but to keep grading simple, please limit the number of possible outcomes to four.
  • You’ll need to include all pieces, in this order:
    • title
    • description
    • number of outcomes & number of questions that matches the rest of your quiz
    • one answer per outcome in each question you write
    • scoring guide, one line per outcome
    • all potential outcomes, one per line

Make sure that your quiz file can be run with your program since it will be worth points!

6. Readme and Submission

A. Readme

Complete readme_quiz.txt in the same way that you have done for previous assignments.

B. Submission

Submit personality_quiz.py, readme_quiz.txt, and my_quiz.quiz you choose to create on Gradescope.

Your code will be tested for runtime and checkstyle errors upon submission.

Please note that the autograder does not reflect your full grade for this assignment—there are manual points awarded for style as well. Additionally, there may be manual deductions in addition to the autograder’s deductions.

Important: Remember to delete the print statements from Checkpoint 3E before submitting.

If you encounter any autograder-related issues, please make a private post on Ed.


Assignment Concept provided by Bhrajit Thakur. This version was written by Harry Smith in 2024.

  1. I think I’m INFJ on the M-B test. The Big Five tells me that I’m quite open and agreeable (nice!) if not so conscientious (ouch). 

  2. Chaotic Good and Ravenclaw.