Previous | Tutorial index | Next
Solidify understanding of for loops, while loops, break, continue, and nested loops through hands-on, progressively challenging coding problems. Develop problem-solving skills by translating real-world requirements into working Python code.
Before diving into code, professional programmers follow a mental framework:
This tutorial is structured as a series of challenges, each building on the concepts from the previous tutorials. Try each one yourself before looking at the solutions!
Problem Statement: Write a program that asks the user for a non-negative integer n and calculates its factorial (n!). The factorial of n is the product of all positive integers from 1 to n.
0! = 1 (by definition)5! = 5 × 4 × 3 × 2 × 1 = 120Key Concept: This is the Accumulation Pattern (specifically multiplication). Use a for loop with range().
Step-by-Step Plan:
n.factorial = 1.for loop with range(1, n+1) to iterate from 1 to n.factorial by each number.n = int(input("Enter a non-negative integer: "))
factorial = 1
# Handle the edge case of 0! = 1
if n == 0:
print("0! = 1")
else:
for i in range(1, n + 1):
factorial = factorial * i
print(f"Step {i}: factorial = {factorial}") # Debug output
print(f"{n}! = {factorial}")
Trace for n = 5:
i = 1: factorial = 1 * 1 = 1i = 2: factorial = 1 * 2 = 2i = 3: factorial = 2 * 3 = 6i = 4: factorial = 6 * 4 = 24i = 5: factorial = 24 * 5 = 1205! = 120Edge Cases to Test:
n = 0: Should output 1n = 1: Should output 1n = 10: Should output 3628800Problem Statement: Write a guessing game where the program generates a random number between 1 and 10 (inclusive). The user has unlimited attempts to guess the number. After each guess, tell the user if they are too high, too low, or correct. When they guess correctly, print "You got it!" and the number of attempts.
Key Concept: This is the Interactive Loop pattern with an unknown number of iterations. Use a while True loop with break when the user guesses correctly. Use a counter to track attempts.
Step-by-Step Plan:
random and generate a secret number between 1 and 10.attempts = 0.while True to loop indefinitely.attempts.break.import random
secret = random.randint(1, 10)
attempts = 0
print("I'm thinking of a number between 1 and 10.")
print("Can you guess it?")
while True:
guess = int(input("Your guess: "))
attempts += 1
if guess < secret:
print("Too low! Try again.")
elif guess > secret:
print("Too high! Try again.")
else:
print(f"You got it! The number was {secret}.")
print(f"It took you {attempts} attempt(s).")
break
Sample Run:
I'm thinking of a number between 1 and 10.
Can you guess it?
Your guess: 5
Too low! Try again.
Your guess: 8
Too high! Try again.
Your guess: 7
You got it! The number was 7.
It took you 3 attempt(s).
Edge Cases to Test:
Problem Statement: Write a program that asks the user for numbers repeatedly. The program should:
'0' (use break).continue).Key Concept: This combines break for the exit condition and continue for skipping invalid (negative) data. This is a Filtering + Accumulation pattern.
Step-by-Step Plan:
total = 0.while True for an indefinite loop.'0', break (exit the loop).continue (skip the addition and go back to the top).total.break), print the total.total = 0
print("Enter numbers to sum. Enter 0 to stop.")
print("Negative numbers will be ignored.")
while True:
user_input = input("Enter a number (0 to stop): ")
if user_input == '0':
break
# Convert to float to handle decimals
number = float(user_input)
if number < 0:
print("Negative number ignored.")
continue
total += number
print(f"Current total: {total}")
print(f"Sum of all positive numbers: {total}")
Sample Run:
Enter numbers to sum. Enter 0 to stop.
Negative numbers will be ignored.
Enter a number (0 to stop): 10
Current total: 10.0
Enter a number (0 to stop): -5
Negative number ignored.
Enter a number (0 to stop): 20
Current total: 30.0
Enter a number (0 to stop): 0
Sum of all positive numbers: 30.0
⚠️ Important: Note how continue works. When we type -5, we skip total += number and go back to the top of the loop. The continue does not skip the if user_input == '0' check (it's already below it).
Problem Statement: Write a program that asks the user for a height h and prints a pyramid of asterisks (*) with h rows.
h = 5, the output should be: *
***
*****
*******
*********
Key Concept: Nested loops with dynamic ranges. The outer loop controls rows. The inner loops control spaces and stars. The number of spaces decreases as the number of stars increases.
Step-by-Step Plan:
h.i from 1 to h:
h - i spaces.2*i - 1 stars.h = int(input("Enter the height of the pyramid: "))
for i in range(1, h + 1):
# Print spaces (h - i spaces)
for j in range(h - i):
print(" ", end="")
# Print stars (2*i - 1 stars)
for k in range(2 * i - 1):
print("*", end="")
# Move to the next line
print()
Trace for h = 5, Row 3 (i = 3):
h - i = 5 - 3 = 2 spaces → " "2*i - 1 = 2*3 - 1 = 5 stars → "*****"" *****"Edge Cases to Test:
h = 1: Should print a single *h = 0 or negative: Should handle gracefully (maybe print nothing or an error message).Problem Statement: Create a simple calculator menu that runs indefinitely until the user chooses to exit. The menu should:
Ask the user for two numbers.
Display a menu:
1. Add
2. Subtract
3. Multiply
4. Divide
5. Exit
Perform the chosen operation and display the result.
Use break to exit when the user chooses option 5.
Key Concept: This is a Menu-Driven Program using while True and break for exit. It combines user input validation and arithmetic operations.
while True:
print("\n=== Simple Calculator ===")
num1 = float(input("Enter first number: "))
num2 = float(input("Enter second number: "))
print("\nChoose an operation:")
print("1. Add")
print("2. Subtract")
print("3. Multiply")
print("4. Divide")
print("5. Exit")
choice = input("Enter your choice (1-5): ")
if choice == '1':
print(f"{num1} + {num2} = {num1 + num2}")
elif choice == '2':
print(f"{num1} - {num2} = {num1 - num2}")
elif choice == '3':
print(f"{num1} * {num2} = {num1 * num2}")
elif choice == '4':
if num2 != 0:
print(f"{num1} / {num2} = {num1 / num2}")
else:
print("Error: Cannot divide by zero!")
elif choice == '5':
print("Goodbye!")
break
else:
print("Invalid choice. Please try again.")
Problem Statement: Extend the pyramid challenge to print a full diamond. For n = 5:
*
***
*****
***
*
Key Concept: The diamond consists of a top pyramid (increasing) and a bottom pyramid (decreasing). Use separate sets of nested loops or a single loop with conditional logic.
n = int(input("Enter an odd number for diamond height: "))
# Top half (including middle)
for i in range(1, n + 1, 2):
spaces = (n - i) // 2
stars = i
for j in range(spaces):
print(" ", end="")
for k in range(stars):
print("*", end="")
print()
# Bottom half (excluding middle)
for i in range(n - 2, 0, -2):
spaces = (n - i) // 2
stars = i
for j in range(spaces):
print(" ", end="")
for k in range(stars):
print("*", end="")
print()
Q1: What is the output of the factorial calculation for n = 4?
a) 24
b) 10
c) 4
Q2: In the Guessing Game, what kind of loop is used?
a) for loop with range()
b) while loop with break
c) Nested loop
Q3: In Challenge 3 (Number Processor), what happens when the user enters -3?
a) It adds -3 to the total.
b) It breaks out of the loop.
c) It skips the number using continue.
Q4: (True/False) The pyramid challenge uses nested loops where the inner loop's range is fixed and independent of the outer loop.
Q5: What does the continue statement do in the context of Challenge 3?
a) Exits the entire program.
b) Skips the rest of the current iteration and goes to the next.
c) Restarts the loop from the beginning.
(Solutions are hidden below – try each one yourself first!)
Exercise 1 (Factorial Variant - Sum of Factorials):
Write a program that calculates the sum of factorials from 1 to n. For n = 3, calculate 1! + 2! + 3! = 1 + 2 + 6 = 9.
(Hint: Use a loop to calculate each factorial and add it to a running total).
n = int(input("Enter a positive integer: "))
total_sum = 0
for i in range(1, n + 1):
# Calculate factorial of i
fact = 1
for j in range(1, i + 1):
fact *= j
total_sum += fact
print(f"{i}! = {fact}") # Optional debug
print(f"Sum of factorials from 1 to {n} = {total_sum}")
Test: For n = 3, output is 1! = 1, 2! = 2, 3! = 6, sum = 9.
Exercise 2 (Guessing Game with Limited Attempts):
Modify the Guessing Game to give the user exactly 5 attempts. If they guess correctly, print "You win!" and the number of attempts used. If they run out of attempts, print "You lose! The number was X."
(Hint: Use a while loop with a counter attempts <= 5 and an if statement to check for a win/loss after the loop).
import random
secret = random.randint(1, 10)
attempts = 5
won = False
print("I'm thinking of a number between 1 and 10.")
print(f"You have {attempts} attempts.")
while attempts > 0:
guess = int(input("Your guess: "))
if guess == secret:
print(f"You win! The number was {secret}.")
won = True
break
elif guess < secret:
print("Too low!")
else:
print("Too high!")
attempts -= 1
if attempts > 0:
print(f"{attempts} attempts left.")
if not won:
print(f"You lose! The number was {secret}.")
Exercise 3 (Number Processor with Statistics):
Extend Challenge 3 to also count how many positive numbers were entered. At the end, print the total, the count, and the average (total / count). Ensure it handles the case where no positive numbers were entered.
total = 0
count = 0
print("Enter numbers to sum. Enter 0 to stop.")
print("Negative numbers will be ignored.")
while True:
user_input = input("Enter a number (0 to stop): ")
if user_input == '0':
break
number = float(user_input)
if number < 0:
print("Negative number ignored.")
continue
total += number
count += 1
print(f"Current total: {total}, Count: {count}")
if count > 0:
average = total / count
print(f"Total: {total}, Count: {count}, Average: {average:.2f}")
else:
print("No positive numbers were entered.")
Exercise 4 (Inverted Pyramid):
Write a program that prints an inverted pyramid for height h.
For h=5:
*********
*******
*****
***
*
(Hint: Start with 2*h - 1 stars and decrease by 2 each row, with increasing spaces).
h = int(input("Enter height: "))
for i in range(h):
# Print leading spaces
for j in range(i):
print(" ", end="")
# Print stars
for k in range(2 * (h - i) - 1):
print("*", end="")
print()
Trace for h=5:
Exercise 5 (Prime Number Checker with Break):
Write a program that asks the user for a number n and checks if it's prime. Use a for loop from 2 to sqrt(n). Use break as soon as you find a divisor. Use an else clause to print "Prime" if no divisor was found.
import math
n = int(input("Enter a positive integer: "))
if n < 2:
print("Not prime")
else:
for d in range(2, int(math.isqrt(n)) + 1):
if n % d == 0:
print(f"Not prime (divisible by {d})")
break
else:
print("Prime")
Test: n=29 → Prime; n=100 → Not prime (divisible by 2).
(Complete sample solutions are provided below – but try to solve them independently first!)
Question 1: The Collatz Sequence (While + Accumulation)
The Collatz sequence starts with any positive integer n:
n is even, divide it by 2 (n = n // 2).n is odd, multiply it by 3 and add 1 (n = 3 * n + 1).n becomes 1.Write a program that asks the user for a starting number and uses a while loop to:
Example for n = 6: Sequence: 6, 3, 10, 5, 16, 8, 4, 2, 1 (Steps: 8, Max: 16)
n = int(input("Enter a starting number: "))
original = n
steps = 0
max_val = n
print(f"Collatz sequence for {n}:", end=" ")
while n != 1:
print(n, end=" ")
if n % 2 == 0:
n = n // 2
else:
n = 3 * n + 1
steps += 1
if n > max_val:
max_val = n
print(1) # Print the final 1
print(f"Steps: {steps}")
print(f"Maximum value: {max_val}")
Test: For n = 6, output matches the example.
Question 2: The Prime Factor Finder (Nested Loops + Break)
Write a program that asks the user for an integer n > 1. Find and print all of its prime factors.
n exactly.n = 84, the prime factors are 2, 2, 3, 7 (since 84 = 2 × 2 × 3 × 7).Hint: Use a while loop to repeatedly divide n by its smallest prime factor. Use a for loop to find the smallest prime factor.
n = int(input("Enter an integer > 1: "))
original = n
print(f"Prime factors of {original}:", end=" ")
d = 2
while d * d <= n:
while n % d == 0:
print(d, end=" ")
n //= d
d += 1
# If anything remains, it is a prime factor > 1
if n > 1:
print(n)
else:
print() # newline
Test: 84 → 2 2 3 7; 13 → 13.
Question 3: The Word Scrambler (For + String Manipulation)
Write a program that takes a word from the user and prints all its characters in reverse order, but only if the word is longer than 3 characters and does not contain the letter 'e'. If the word fails any of these conditions, print "Invalid word" and ask again (using a while loop).
Example:
while True:
word = input("Enter a word: ")
# Check conditions
if len(word) <= 3:
print("Invalid word (too short)")
elif 'e' in word.lower(): # case-insensitive check
print("Invalid word (contains 'e')")
else:
# Reverse the word using a for loop
reversed_word = ""
for char in word:
reversed_word = char + reversed_word
print(f"Scrambled: {reversed_word}")
break # exit the loop after a valid word
Question 4: The Student Grade Analyzer (Data Analysis)
You are given a list of dictionaries (or tuples) containing student names and grades:
students = [
("Alice", 85),
("Bob", 72),
("Charlie", 93),
("David", 67),
("Eve", 88)
]
Write a program that:
students = [
("Alice", 85),
("Bob", 72),
("Charlie", 93),
("David", 67),
("Eve", 88)
]
total = 0
highest = -1
lowest = 101
passed = 0
a_students = []
for name, grade in students:
# Accumulation
total += grade
# Search for highest and lowest
if grade > highest:
highest = grade
if grade < lowest:
lowest = grade
# Count passed
if grade >= 70:
passed += 1
# Filter A students
if grade >= 90:
a_students.append(name)
average = total / len(students)
print(f"Class Average: {average:.2f}")
print(f"Highest Grade: {highest}")
print(f"Lowest Grade: {lowest}")
print(f"Number of students who passed: {passed}")
print(f"Students with an 'A': {a_students}")
Question 5: The Diamond Calculator (Pattern + Loops)
Write a program that prints a diamond made of numbers instead of stars. For n = 5:
1
232
34543
4567654
567898765
4567654
34543
232
1
(Hint: The numbers in each row follow a pattern: they increase to the middle of the row, then decrease. The logic requires careful calculation of the start and end values for each row).
n = int(input("Enter the size (number of rows in top half): "))
# Top half (including the middle row)
for i in range(1, n + 1):
# Print leading spaces
spaces = n - i
print(" " * spaces, end="")
# Start value for this row
start = i
# Middle value (maximum) for this row
mid = 2 * i - 1
# Ascending part: from start to mid
for num in range(start, mid + 1):
print(num, end="")
# Descending part: from mid-1 down to start
for num in range(mid - 1, start - 1, -1):
print(num, end="")
print() # newline
# Bottom half (excluding the middle row)
for i in range(n - 1, 0, -1):
spaces = n - i
print(" " * spaces, end="")
start = i
mid = 2 * i - 1
for num in range(start, mid + 1):
print(num, end="")
for num in range(mid - 1, start - 1, -1):
print(num, end="")
print()
Test: For n = 5, the output matches the required diamond exactly.
After completing these challenges, take a moment to reflect:
break vs continue?Key Takeaways:
for loops are for known sequences (range, lists, strings).while loops are for unknown iteration counts (user input, conditions).break exits the loop immediately.continue skips the current iteration.You are now ready for the next unit! The skills you've practiced here are foundational. In the next unit, you'll learn about functions, which will allow you to package these loops into reusable, organized code blocks.
Congratulations on completing six tutorials on loops! You've built a strong foundation in one of programming's most essential concepts. Keep practicing, and remember: the best way to learn programming is to write code, make mistakes, and learn from them. Happy coding! 🚀