Making Decisions and Repeating Work

Adding Choices and Repetition to Your Study Log


This chapter is the project checkpoint for Part 2. The study log you built the previous part handled exactly one session — ask, respond, exit. This part, it grows into something that actually feels like a tracker: it handles many sessions in one run, it reacts differently to different sessions, and it ends with a small summary of what was logged.

What the Study Log Does Now

By the end of this checkpoint, your study log:

  1. Asks for sessions one at a time in a loop, until the user types done.
  2. Stores each session (subject and minutes) so the program can use it later.
  3. Reacts to each session with a different message depending on how long it was.
  4. Prints a summary at the end: the number of sessions, the total minutes, the average session length, and the longest session.

Nothing in this version saves data between runs. When you stop the program, everything you logged is gone. Persistence — actually saving to a file — arrives in Part 4. For now, the program is a single-run experience.

The Shape of the Main Loop

The main loop is the while True: ... break pattern from While Loops and Range. The skeleton looks like this:

subjects = []
minutes_list = []
while True:
subject = input("Subject (or 'done' to finish): ").strip().lower()
if subject == "done":
break
minutes_text = input("For how many minutes? ").strip()
minutes = int(minutes_text)
subjects.append(subject)
minutes_list.append(minutes)
# ... respond to this session here ...
# ... summary here, after the loop ...

Read this carefully before writing your own version. Three things are worth noticing:

  • The two lists, subjects and minutes_list, are set up before the loop. They start empty. The loop appends to them.
  • The check if subject == "done": break uses the normalized input (.strip().lower()), so Done, done , and DONE all work as quit signals.
  • The summary lives outside the loop. It only runs once, after the user has quit.

Indentation is what controls which lines are inside the loop and which are outside. Get that wrong and the summary will run on every iteration, or the appends will run after the loop — both common Part 2 bugs.

A Worked Second Version

Here is a complete working version. Your own version does not need to match this exactly.

print("=== Study Log ===")
print()
subjects = []
minutes_list = []
while True:
subject = input("Subject (or 'done' to finish): ").strip().lower()
if subject == "done":
break
minutes_text = input("For how many minutes? ").strip()
minutes = int(minutes_text)
subjects.append(subject)
minutes_list.append(minutes)
# Response based on session length
if minutes < 15:
print(f" Short session on {subject} -- every bit counts.")
elif minutes <= 90:
print(f" Solid session on {subject}.")
else:
print(f" Long session on {subject} -- remember to take breaks!")
print()
# Summary
print("=== Summary ===")
if len(minutes_list) == 0:
print("No sessions logged today.")
else:
total = 0
for m in minutes_list:
total += m
average = total / len(minutes_list)
longest = minutes_list[0]
for m in minutes_list:
if m > longest:
longest = m
print(f"Sessions: {len(minutes_list)}")
print(f"Total minutes: {total}")
print(f"Average session: {average:.1f} minutes")
print(f"Longest session: {longest} minutes")

When you run this program and enter, say, Math for 45, Physics for 90, done — the output looks something like:

=== Study Log ===
Subject (or 'done' to finish): Math
For how many minutes? 45
Solid session on math.
Subject (or 'done' to finish): Physics
For how many minutes? 90
Solid session on physics.
Subject (or 'done' to finish): done
=== Summary ===
Sessions: 2
Total minutes: 135
Average session: 67.5 minutes
Longest session: 90 minutes

Read this program line by line and trace it with two sessions. Then trace it again with zero sessions (the user just types done immediately). The if len(minutes_list) == 0: guard is what keeps the empty case from crashing.

Why Parallel Lists?

You may notice that the program uses two separate lists — subjects and minutes_list — that need to be kept in sync. The first item of subjects corresponds to the first item of minutes_list, the second to the second, and so on. This is called parallel lists, and it has a real downside: nothing in the language stops you from accidentally appending to one list but not the other, and the two can get out of sync.

A more experienced programmer would probably use a dictionary or a small class to keep each session’s data together. That is exactly what you will learn in Part 6. For now, parallel lists are pedagogically clean: each list grows on its own, you can see exactly what is happening, and the loop patterns from Counting, Accumulating, and Searching apply directly.

When you switch the project to dictionaries in Part 6, you will get to feel the upgrade in a real way. That is more valuable than skipping straight to the polished version now.

Your Turn

Build your own version. Requirements:

  1. One while loop that keeps asking for sessions until the user types done.
  2. At least one if/elif/else that branches on something about the session (length, subject, or anything else you choose).
  3. At least two parallel lists holding the session data.
  4. A summary at the end that uses at least two of the loop patterns from Counting, Accumulating, and Searching. Total and longest is one combination; total and “long-session count” is another; average and shortest is another.
  5. A reasonable response to the common edge cases:
    • The user types done immediately, before logging any sessions. The summary should not crash.
    • The user types Done or done (with a trailing space). The program should accept it.
    • A session of 0 minutes should be handled sensibly. Whether that means accepting it, rejecting it, or just logging it is your choice — but the program should not crash.

Study log with choices and repetition

0 / 20 points

Build the Week 2 study log.

Your program must:

  • print an introduction line that includes Study Log,
  • repeatedly ask for a subject until the user types done,
  • accept Done, DONE, and done as quit signals by normalizing the subject with .strip().lower(),
  • ask for minutes only after a non-quit subject,
  • store subjects and minutes in two parallel lists,
  • print a response for each logged session using if/elif/else,
  • and print a summary after the loop.

The summary must include:

  • the number of sessions,
  • the total minutes,
  • the average minutes rounded to one decimal place,
  • and the longest session in minutes.

If no sessions are logged, print No sessions logged. and do not divide by zero.

Example input:

Math
45
Art
90
Done

Required output text:

Study Log
Solid session on math.
Solid session on art.
Sessions: 2
Total minutes: 135
Average minutes: 67.5
Longest session: 90

The exact input prompts may differ. The required output lines above must appear exactly as written.

Things to Try Beyond the Minimum

If you finish the minimum and want to keep going, here are some suggestions. None of these are required.

  • Count sessions per subject. A loop that walks subjects and counts how many times each subject appears. Print the subject with the most sessions.
  • Find the most-studied subject by total minutes (not session count).
  • Show a goal-progress message. Set a daily goal of, say, 120 minutes, and print how much of it the user hit.
  • Reject zero-minute sessions with a polite message rather than logging them.
  • Show all logged sessions in the summary as a numbered list, before the totals.

Each of these is small and gives you more practice with the loop patterns from this part.

Common Pitfalls

A short list of things that often trip students up on this project:

  • Forgetting int(...) inside the loop. minutes is text when it comes back from input(...). The loop has to convert it before appending, or every comparison and total later will be wrong.
  • Not handling the empty case in the summary. If done is the first thing typed, minutes_list is empty. Dividing by len(minutes_list) will crash. The if len(minutes_list) == 0: guard is what fixes this.
  • Indentation putting the summary inside the loop. A subtle bug: the summary lines should be at the same indentation as the while, not inside it. Otherwise the summary prints on every iteration.
  • Out-of-sync parallel lists. Appending to one list but not the other, usually because of an early continue or break. Trace your loop with the empty-input case to catch this.
  • Quit signal not matching. Forgetting .strip().lower(), so Done does not quit the program.

If you hit one of these, the right response is the same as the previous part: trace what is happening, add a debug print if needed, fix the one specific issue, and run again.