You're printing a 10×10 multiplication table. For each row (1-10), you need to print 10 products (row × 1, row × 2, ... row × 10). The outer loop picks the row; the inner loop fills each column.

Multiplication table

Generate a multiplication table using nested loops.

multiplication.py
size = 

# Print header
print("   ", end="")
for i in range(1, size + 1):
    print(f"{i:4d}", end="")
print()
print("   " + "-" * (size * 4))

# Print table
for row in range(1, size + 1):
    print(f"{row:2d} |", end="")
    for col in range(1, size + 1):
        print(f"{row * col:4d}", end="")
    print()


size = 

# Print header
print("   ", end="")
for i in range(1, size + 1):
    print(f"{i:4d}", end="")
print()
print("   " + "-" * (size * 4))

# Print table
for row in range(1, size + 1):
    print(f"{row:2d} |", end="")
    for col in range(1, size + 1):
        print(f"{row * col:4d}", end="")
    print()


size = 

# Print header
print("   ", end="")
for i in range(1, size + 1):
    print(f"{i:4d}", end="")
print()
print("   " + "-" * (size * 4))

# Print table
for row in range(1, size + 1):
    print(f"{row:2d} |", end="")
    for col in range(1, size + 1):
        print(f"{row * col:4d}", end="")
    print()


Outer loop: each row (1-10). Inner loop: each column (multiply by 1-10).

nested loop A loop inside another loop. Inner completes fully for each outer iteration.

Print rectangle of stars

Draw a rectangle pattern with asterisks.

rectangle.py
width = 
height = 

print(f"Rectangle {width}x{height}:")

for row in range(height):
    for col in range(width):
        print("* ", end="")
    print()  # New line after each row

# Hollow rectangle
print("\nHollow rectangle:")
for row in range(height):
    for col in range(width):
        if row == 0 or row == height - 1 or col == 0 or col == width - 1:
            print("* ", end="")
        else:
            print("  ", end="")
    print()

# Pythonic: string multiplication
print("\nUsing string multiplication:")
for row in range(height):
    print("* " * width)
width = 
height = 

print(f"Rectangle {width}x{height}:")

for row in range(height):
    for col in range(width):
        print("* ", end="")
    print()  # New line after each row

# Hollow rectangle
print("\nHollow rectangle:")
for row in range(height):
    for col in range(width):
        if row == 0 or row == height - 1 or col == 0 or col == width - 1:
            print("* ", end="")
        else:
            print("  ", end="")
    print()

# Pythonic: string multiplication
print("\nUsing string multiplication:")
for row in range(height):
    print("* " * width)
width = 
height = 

print(f"Rectangle {width}x{height}:")

for row in range(height):
    for col in range(width):
        print("* ", end="")
    print()  # New line after each row

# Hollow rectangle
print("\nHollow rectangle:")
for row in range(height):
    for col in range(width):
        if row == 0 or row == height - 1 or col == 0 or col == width - 1:
            print("* ", end="")
        else:
            print("  ", end="")
    print()

# Pythonic: string multiplication
print("\nUsing string multiplication:")
for row in range(height):
    print("* " * width)
width = 
height = 

print(f"Rectangle {width}x{height}:")

for row in range(height):
    for col in range(width):
        print("* ", end="")
    print()  # New line after each row

# Hollow rectangle
print("\nHollow rectangle:")
for row in range(height):
    for col in range(width):
        if row == 0 or row == height - 1 or col == 0 or col == width - 1:
            print("* ", end="")
        else:
            print("  ", end="")
    print()

# Pythonic: string multiplication
print("\nUsing string multiplication:")
for row in range(height):
    print("* " * width)
width = 
height = 

print(f"Rectangle {width}x{height}:")

for row in range(height):
    for col in range(width):
        print("* ", end="")
    print()  # New line after each row

# Hollow rectangle
print("\nHollow rectangle:")
for row in range(height):
    for col in range(width):
        if row == 0 or row == height - 1 or col == 0 or col == width - 1:
            print("* ", end="")
        else:
            print("  ", end="")
    print()

# Pythonic: string multiplication
print("\nUsing string multiplication:")
for row in range(height):
    print("* " * width)
width = 
height = 

print(f"Rectangle {width}x{height}:")

for row in range(height):
    for col in range(width):
        print("* ", end="")
    print()  # New line after each row

# Hollow rectangle
print("\nHollow rectangle:")
for row in range(height):
    for col in range(width):
        if row == 0 or row == height - 1 or col == 0 or col == width - 1:
            print("* ", end="")
        else:
            print("  ", end="")
    print()

# Pythonic: string multiplication
print("\nUsing string multiplication:")
for row in range(height):
    print("* " * width)
width = 
height = 

print(f"Rectangle {width}x{height}:")

for row in range(height):
    for col in range(width):
        print("* ", end="")
    print()  # New line after each row

# Hollow rectangle
print("\nHollow rectangle:")
for row in range(height):
    for col in range(width):
        if row == 0 or row == height - 1 or col == 0 or col == width - 1:
            print("* ", end="")
        else:
            print("  ", end="")
    print()

# Pythonic: string multiplication
print("\nUsing string multiplication:")
for row in range(height):
    print("* " * width)
width = 
height = 

print(f"Rectangle {width}x{height}:")

for row in range(height):
    for col in range(width):
        print("* ", end="")
    print()  # New line after each row

# Hollow rectangle
print("\nHollow rectangle:")
for row in range(height):
    for col in range(width):
        if row == 0 or row == height - 1 or col == 0 or col == width - 1:
            print("* ", end="")
        else:
            print("  ", end="")
    print()

# Pythonic: string multiplication
print("\nUsing string multiplication:")
for row in range(height):
    print("* " * width)
width = 
height = 

print(f"Rectangle {width}x{height}:")

for row in range(height):
    for col in range(width):
        print("* ", end="")
    print()  # New line after each row

# Hollow rectangle
print("\nHollow rectangle:")
for row in range(height):
    for col in range(width):
        if row == 0 or row == height - 1 or col == 0 or col == width - 1:
            print("* ", end="")
        else:
            print("  ", end="")
    print()

# Pythonic: string multiplication
print("\nUsing string multiplication:")
for row in range(height):
    print("* " * width)

Outer loop: rows. Inner loop: columns within each row.

Print triangle pattern

Create a right triangle by varying inner loop iterations.

triangle.py
height = 

# Right triangle (left-aligned)
print("Right triangle:")
for row in range(1, height + 1):
    for col in range(row):
        print("* ", end="")
    print()

# Inverted triangle
print("\nInverted triangle:")
for row in range(height, 0, -1):
    for col in range(row):
        print("* ", end="")
    print()

# Right-aligned triangle
print("\nRight-aligned triangle:")
for row in range(1, height + 1):
    print("  " * (height - row), end="")  # spaces
    print("* " * row)                      # stars

# Pythonic versions
print("\nPythonic right triangle:")
for row in range(1, height + 1):
    print("* " * row)

height = 

# Right triangle (left-aligned)
print("Right triangle:")
for row in range(1, height + 1):
    for col in range(row):
        print("* ", end="")
    print()

# Inverted triangle
print("\nInverted triangle:")
for row in range(height, 0, -1):
    for col in range(row):
        print("* ", end="")
    print()

# Right-aligned triangle
print("\nRight-aligned triangle:")
for row in range(1, height + 1):
    print("  " * (height - row), end="")  # spaces
    print("* " * row)                      # stars

# Pythonic versions
print("\nPythonic right triangle:")
for row in range(1, height + 1):
    print("* " * row)

height = 

# Right triangle (left-aligned)
print("Right triangle:")
for row in range(1, height + 1):
    for col in range(row):
        print("* ", end="")
    print()

# Inverted triangle
print("\nInverted triangle:")
for row in range(height, 0, -1):
    for col in range(row):
        print("* ", end="")
    print()

# Right-aligned triangle
print("\nRight-aligned triangle:")
for row in range(1, height + 1):
    print("  " * (height - row), end="")  # spaces
    print("* " * row)                      # stars

# Pythonic versions
print("\nPythonic right triangle:")
for row in range(1, height + 1):
    print("* " * row)

The inner loop's limit depends on the outer loop variable.

Search in 2D grid

Find a value in a 2D list (matrix).

grid_search.py
grid = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
]
target = 

# Print the grid
print("Grid:")
for row in grid:
    for cell in row:
        print(f"{cell:3d}", end="")
    print()

# Search for target (using break with flag)
found_pos = None
for row_idx, row in enumerate(grid):
    for col_idx, cell in enumerate(row):
        if cell == target:
            found_pos = (row_idx, col_idx)
            break
    if found_pos:
        break

if found_pos:
    print(f"\nFound {target} at [{found_pos[0]}][{found_pos[1]}]")
else:
    print(f"\n{target} not found in grid")

# Pythonic: using next() with generator
print("\nUsing generator expression:")
result = next(
    ((r, c) for r, row in enumerate(grid) for c, val in enumerate(row) if val == target),
    None
)
print(f"Result: {result}")
grid = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
]
target = 

# Print the grid
print("Grid:")
for row in grid:
    for cell in row:
        print(f"{cell:3d}", end="")
    print()

# Search for target (using break with flag)
found_pos = None
for row_idx, row in enumerate(grid):
    for col_idx, cell in enumerate(row):
        if cell == target:
            found_pos = (row_idx, col_idx)
            break
    if found_pos:
        break

if found_pos:
    print(f"\nFound {target} at [{found_pos[0]}][{found_pos[1]}]")
else:
    print(f"\n{target} not found in grid")

# Pythonic: using next() with generator
print("\nUsing generator expression:")
result = next(
    ((r, c) for r, row in enumerate(grid) for c, val in enumerate(row) if val == target),
    None
)
print(f"Result: {result}")
grid = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
]
target = 

# Print the grid
print("Grid:")
for row in grid:
    for cell in row:
        print(f"{cell:3d}", end="")
    print()

# Search for target (using break with flag)
found_pos = None
for row_idx, row in enumerate(grid):
    for col_idx, cell in enumerate(row):
        if cell == target:
            found_pos = (row_idx, col_idx)
            break
    if found_pos:
        break

if found_pos:
    print(f"\nFound {target} at [{found_pos[0]}][{found_pos[1]}]")
else:
    print(f"\n{target} not found in grid")

# Pythonic: using next() with generator
print("\nUsing generator expression:")
result = next(
    ((r, c) for r, row in enumerate(grid) for c, val in enumerate(row) if val == target),
    None
)
print(f"Result: {result}")
grid = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
]
target = 

# Print the grid
print("Grid:")
for row in grid:
    for cell in row:
        print(f"{cell:3d}", end="")
    print()

# Search for target (using break with flag)
found_pos = None
for row_idx, row in enumerate(grid):
    for col_idx, cell in enumerate(row):
        if cell == target:
            found_pos = (row_idx, col_idx)
            break
    if found_pos:
        break

if found_pos:
    print(f"\nFound {target} at [{found_pos[0]}][{found_pos[1]}]")
else:
    print(f"\n{target} not found in grid")

# Pythonic: using next() with generator
print("\nUsing generator expression:")
result = next(
    ((r, c) for r, row in enumerate(grid) for c, val in enumerate(row) if val == target),
    None
)
print(f"Result: {result}")

Nested loops to traverse all [row][col] positions.

row-major Process row by row: outer loop = rows, inner loop = columns.

Compare all pairs

Find all pairs that satisfy a condition.

pairs.py
numbers = 
target_sum = 

print(f"Find pairs that sum to {target_sum}:")

# All pairs (avoiding duplicates)
print(f"\nAll pairs with sum {target_sum}:")
for i in range(len(numbers)):
    for j in range(i + 1, len(numbers)):
        if numbers[i] + numbers[j] == target_sum:
            print(f"  {numbers[i]} + {numbers[j]} = {target_sum}")

# All possible pairs (cartesian product)
print("\nAll pairs (order matters):")
for i in range(len(numbers)):
    for j in range(len(numbers)):
        if i != j:
            print(f"  ({numbers[i]}, {numbers[j]})")

# Pythonic: using itertools
from itertools import combinations, permutations

print(f"\nUsing combinations:")
for a, b in combinations(numbers, 2):
    if a + b == target_sum:
        print(f"  {a} + {b} = {target_sum}")

print("\nUsing permutations:")
for pair in permutations(numbers, 2):
    print(f"  {pair}")

numbers = 
target_sum = 

print(f"Find pairs that sum to {target_sum}:")

# All pairs (avoiding duplicates)
print(f"\nAll pairs with sum {target_sum}:")
for i in range(len(numbers)):
    for j in range(i + 1, len(numbers)):
        if numbers[i] + numbers[j] == target_sum:
            print(f"  {numbers[i]} + {numbers[j]} = {target_sum}")

# All possible pairs (cartesian product)
print("\nAll pairs (order matters):")
for i in range(len(numbers)):
    for j in range(len(numbers)):
        if i != j:
            print(f"  ({numbers[i]}, {numbers[j]})")

# Pythonic: using itertools
from itertools import combinations, permutations

print(f"\nUsing combinations:")
for a, b in combinations(numbers, 2):
    if a + b == target_sum:
        print(f"  {a} + {b} = {target_sum}")

print("\nUsing permutations:")
for pair in permutations(numbers, 2):
    print(f"  {pair}")

numbers = 
target_sum = 

print(f"Find pairs that sum to {target_sum}:")

# All pairs (avoiding duplicates)
print(f"\nAll pairs with sum {target_sum}:")
for i in range(len(numbers)):
    for j in range(i + 1, len(numbers)):
        if numbers[i] + numbers[j] == target_sum:
            print(f"  {numbers[i]} + {numbers[j]} = {target_sum}")

# All possible pairs (cartesian product)
print("\nAll pairs (order matters):")
for i in range(len(numbers)):
    for j in range(len(numbers)):
        if i != j:
            print(f"  ({numbers[i]}, {numbers[j]})")

# Pythonic: using itertools
from itertools import combinations, permutations

print(f"\nUsing combinations:")
for a, b in combinations(numbers, 2):
    if a + b == target_sum:
        print(f"  {a} + {b} = {target_sum}")

print("\nUsing permutations:")
for pair in permutations(numbers, 2):
    print(f"  {pair}")

numbers = 
target_sum = 

print(f"Find pairs that sum to {target_sum}:")

# All pairs (avoiding duplicates)
print(f"\nAll pairs with sum {target_sum}:")
for i in range(len(numbers)):
    for j in range(i + 1, len(numbers)):
        if numbers[i] + numbers[j] == target_sum:
            print(f"  {numbers[i]} + {numbers[j]} = {target_sum}")

# All possible pairs (cartesian product)
print("\nAll pairs (order matters):")
for i in range(len(numbers)):
    for j in range(len(numbers)):
        if i != j:
            print(f"  ({numbers[i]}, {numbers[j]})")

# Pythonic: using itertools
from itertools import combinations, permutations

print(f"\nUsing combinations:")
for a, b in combinations(numbers, 2):
    if a + b == target_sum:
        print(f"  {a} + {b} = {target_sum}")

print("\nUsing permutations:")
for pair in permutations(numbers, 2):
    print(f"  {pair}")

numbers = 
target_sum = 

print(f"Find pairs that sum to {target_sum}:")

# All pairs (avoiding duplicates)
print(f"\nAll pairs with sum {target_sum}:")
for i in range(len(numbers)):
    for j in range(i + 1, len(numbers)):
        if numbers[i] + numbers[j] == target_sum:
            print(f"  {numbers[i]} + {numbers[j]} = {target_sum}")

# All possible pairs (cartesian product)
print("\nAll pairs (order matters):")
for i in range(len(numbers)):
    for j in range(len(numbers)):
        if i != j:
            print(f"  ({numbers[i]}, {numbers[j]})")

# Pythonic: using itertools
from itertools import combinations, permutations

print(f"\nUsing combinations:")
for a, b in combinations(numbers, 2):
    if a + b == target_sum:
        print(f"  {a} + {b} = {target_sum}")

print("\nUsing permutations:")
for pair in permutations(numbers, 2):
    print(f"  {pair}")

numbers = 
target_sum = 

print(f"Find pairs that sum to {target_sum}:")

# All pairs (avoiding duplicates)
print(f"\nAll pairs with sum {target_sum}:")
for i in range(len(numbers)):
    for j in range(i + 1, len(numbers)):
        if numbers[i] + numbers[j] == target_sum:
            print(f"  {numbers[i]} + {numbers[j]} = {target_sum}")

# All possible pairs (cartesian product)
print("\nAll pairs (order matters):")
for i in range(len(numbers)):
    for j in range(len(numbers)):
        if i != j:
            print(f"  ({numbers[i]}, {numbers[j]})")

# Pythonic: using itertools
from itertools import combinations, permutations

print(f"\nUsing combinations:")
for a, b in combinations(numbers, 2):
    if a + b == target_sum:
        print(f"  {a} + {b} = {target_sum}")

print("\nUsing permutations:")
for pair in permutations(numbers, 2):
    print(f"  {pair}")

Comparing every element with every other element requires O(n²) nested loops.

O(n²) Time complexity when nested loops both iterate n times.
comprehension Python's nested list comprehensions can replace some nested loops.

Exercise: diamond.py

Create a diamond shape pattern with careful loop control