Multiplication Triangle in Python

Beginner
⏱️ 9 min read
📚 Updated: Sep 2026
🎯 3 Code Examples
🚀 Live Preview
Nested Loops + Multiplication

What You’ll Learn

Program 49 prints a triangular multiplication pattern: row i shows i*1, i*2, … up to i*i — a natural step after Program 48’s single-loop sequence. This tutorial covers nested loops with i*j products, a live preview, worked Python examples, edge cases, and complexity.

Shape Rule

i*j products

Row i prints i values: i*1, i*2, …, i*i.

Outer Loop

i = 1..rows

for i in range(1, rows + 1): picks the row multiplier.

Inner Loop

j = 1..i

for j in range(1, i + 1): prints each product on the row.

Last Value

i*i

Each row ends with i*i — row 5 ends with 25.

Live Preview

rows = 3..10

Pick row count and draw the multiplication triangle in the browser.

O(n²)

Complexity

Total prints = n(n+1)/2 — a triangular number.

Introduction

A triangular multiplication pattern prints row i with i products: multiply i by 1, 2, … up to i. With rows = 4, you get 1, then 2 4, then 3 6 9, then 4 8 12 16.

In Python nested loops handle this: outer i = 1..rows, inner j = 1..i, print(i * j, end=" "), then print().

Why it matters?

It bridges Program 48’s single loop to full nested-loop grids — core multiplication-table thinking.

Key Highlights

Outer = row

i is the multiplier.

Inner = column

j runs 1..i.

vs Program 48

Program 48 is 1D sequence; Program 49 is nested-loop triangle.

Series Foundation

Follow Program 48; continue to Program 50 next.

In short: outer i = 1..rows, inner j = 1..i, print(i*j, end=" "), then print().

📝 Problem & Approach

Given row count rows = 10, print a triangular multiplication pattern — row i shows i products from i*1 to i*i.

Python
# rows = 10
//1
//2 4
//3 6 9
//4 8 12 16
//5 10 15 20 25
// ... up to row 10

Inputs & Outputs

ItemTypeDescription
rowsintHow many triangle rows to print.
i (outer)intRow multiplier — runs from 1 to rows.
j (inner)intColumn index — runs from 1 to i on each row.
Cell valueinti * j — last value on row i is i*i.

Minimal workflow

Pseudocode
for i from 1 to rows:
    for j from 1 to i:
        print i * j
    print newline

Approach comparison

ApproachIdeaBest for
Nested loopsi*j with inner j = 1..iLearning and interviews
User-input rowsrows = int(input())Flexible row count
Aligned formattingprint(f"{i*j:4d}", end=" ")Aligned columns for larger rows
Full table variantInner loop j = 1..rows every rowRectangular multiplication grid

⚡ Quick Reference

GoalPattern
Outer loopfor i in range(1, rows + 1):
Inner loopfor j in range(1, i + 1):
Print productprint(i * j, end=" ")
End rowprint()
Last value on row ii * i (e.g. row 5 ends with 25)
Full table tweakChange inner to j <= rows
Program 48 contrastProgram 48 is 1D sequence; Program 49 is nested-loop triangle

📋 Fixed Rows vs User Input vs Compact Trace

Same triangle — three ways to set row count and format output.

Fixed rows
rows = 10

Hard-coded height for demos

User input
int(input())

Read row count from console

Compact trace
rows = 5

Quick dry-run on paper

Aligned cols
{i*j,4}

Fixed-width for readability

Cell rule
i * j

Product of row and column

Context

When This Pattern Shows Up

Reach for this pattern when teaching nested loops, multiplication tables, and growing inner bounds.

  1. Post Program 48 exercise

    Natural follow-up after Program 48’s single loop — introduces nested loops with changing inner bounds.

  2. Multiplication tables

    Row i is the i-times table — visual bridge to arithmetic grids.

  3. Triangular numbers

    Total prints = n(n+1)/2 — classic nested-loop complexity example.

  4. Gateway to variants

    Compare Program 48 (1D sequence) and Program 50 (next in series) next.

  5. Not a UI layout tool

    This is a console teaching pattern — not how you build modern app screens.

Key benefit: one small program that locks in nested loops, i*j logic, and O(n²) thinking.

🔮 Live Preview

Choose row count between 3 and 10 and draw the multiplication triangle in the browser.

Try 4, 5, or 8. Max up to 10 in this preview.

Live result
Press "Draw pattern".

Examples Gallery

Three complete Python programs — fixed rows = 10, user input with aligned formatting, and compact rows = 5 trace demo. Click View Output to reveal sample console results.

📚 Getting Started

Print ten rows of the multiplication triangle with nested loops and i*j products.

Example 1 — Fixed rows = 10

Hard-coded height — outer loop picks row i, inner loop prints i*j.

Python
rows = 10

for i in range(1, rows + 1):
    for j in range(1, i + 1):
        print(i * j, end=" ")
    print()

How It Works

When i = 3, the inner loop prints 3*1=3, 3*2=6, 3*3=9. Each row has exactly i values; the last is always i*i.

📈 User Input

Read row count with int(input()) and use aligned formatting.

Example 2 — User Input + Aligned Formatting

Read rows with int(input()) and print a neatly aligned triangle.

Python
try:
    rows = int(input("Enter number of rows: "))
except ValueError:
    print("Please enter a positive integer.")
    raise SystemExit(1)

if rows < 1:
    print("rows must be at least 1")
    raise SystemExit(1)

for i in range(1, rows + 1):
    for j in range(1, i + 1):
        print(f"{i * j:4d}", end=" ")
    print()

How It Works

Same nested-loop core as Example 1; only the source of rows changes. The triangle grows or shrinks based on user input.

⚡ Compact Trace

Smaller row count for quick tracing on paper or in interviews.

Example 3 — Compact rows = 5

Use rows = 5 to trace both loops quickly before scaling to 10 rows.

Python
rows = 5

for i in range(1, rows + 1):
    for j in range(1, i + 1):
        print(i * j, end=" ")
    print()

How It Works

Five rows total — row 5 ends with 25 because the last product is 5*5. Easy to dry-run before coding the full 10-row demo.

🧠 How the Algorithm Prints Rows

1

Choose row count

Set rows = 10 or read from user input — controls triangle height.

Setup
2

Outer loop — row multiplier

for i in range(1, rows + 1): — on each row, i is the base multiplier.

Outer
3

Inner loop — print products

for j in range(1, i + 1): prints i*j with end=" ".

Inner
4

New line per row

print() after the inner loop finishes each row.

Break
=

Multiplication triangle complete

Total prints = n(n+1)/2O(n²) time, O(1) extra memory.

🔎 Worked Walkthrough — row i = 4

Trace inner-loop columns j on row 4 — which product prints for each cell.

ji*jPrints
14*14
24*28
34*312
44*416

Full row 4 output: 4 8 12 16. Row 5 would end with 25 because the last product is 5*5.

Use Cases

Where this tiny pattern (and its loop structure) shows up beyond the homework prompt.

1. Teaching Nested Loops

Inner bound grows with outer index — classic nested-loop exercise.

Example: trace row i = 4 in the walkthrough table.

2. Multiplication Tables

Row i is the i-times table — visual arithmetic bridge.

Example: row 5 ends with 25 = 5*5.

3. Output Formatting Drills

Practice print(..., end=" ") vs print() — multiple values per row vs row breaks.

Example: put print() inside the inner loop by mistake.

4. Triangular Numbers

Total prints = n(n+1)/2 — links loops to summation formulas.

Example: 10 rows print 55 values total.

5. Complexity Intuition

Growing inner bound makes O(n²) concrete — count prints for n rows.

Example: 5 rows = 1+2+3+4+5 = 15 prints.

6. Input Validation Labs

Pair the pattern with try/except ValueError and positive-row checks.

Example: reject rows <= 0 and re-prompt.

Pro Tip: when an interviewer asks for patterns, explain outer/inner roles first — then write the loops. The story matters as much as the code.

Advantages

Why this pattern earns a permanent spot in beginner Python courses.

  1. 1. Instant Visual Feedback

    Wrong inner bounds show up immediately as a broken triangle.

  2. 2. Real Math Connection

    Each row is a mini multiplication table — not abstract loop drill.

  3. 3. Easy to Extend

    Change rows, use fixed-width format, or switch to full rectangular table.

  4. 4. O(1) Extra Memory

    Streaming output needs no storage beyond loop counters.

Pro Tip: trace row i = 4 on paper — watch how inner j runs from 1 to 4 producing 4, 8, 12, 16.

Usage Tips

Small habits that keep number-pattern code clean.

  1. 1. Inner bound = i

    Row i prints exactly i values — use j <= i.

  2. 2. Call try/except ValueError

    Avoid using uninitialized rows when the user types letters instead of a number.

  3. 3. Newline After Inner Loop

    Only call print() after the inner loop finishes the row.

  4. 4. Fixed-Width Formatting

    Use f"{i*j:4d}" for aligned columns on larger rows.

  5. 5. Dry-Run rows = 5

    Trace five rows on paper before coding the full 10-row demo.

Pro Tip: if the output is a vertical list of single numbers, you almost certainly put print() inside the inner loop.

Common Pitfalls

Mistakes that commonly break triangular multiplication patterns.

  1. 1. Newline Inside Inner Loop

    Each product lands on its own line — you get a column, not a triangle.

    → Use print(i * j, end=" ") per cell; print() only after inner loop.

  2. 2. Wrong Inner Bound

    Using j <= rows every row makes a full rectangle, not a triangle.

    → Use for j in range(1, i + 1): — inner bound depends on outer i.

  3. 3. Swapping i and j in Product

    j*i equals i*j here, but order matters in other patterns — stay consistent.

    → Pick one form (i*j or j*i) and use it throughout.

  4. 4. Forgetting Newline After Row

    All products print on one long line without row breaks.

    → Add print() after each inner loop completes.

  5. 5. Bare int(input())

    Letters or empty input raise ValueError with bare int(input()).

    → Catch ValueError and re-prompt on failure.

Edge Cases

Check these inputs before calling the solution done.

rows = 1

Single row

Output is just 1 on one line.

rows = 0

Empty output

Outer loop never runs — print nothing or show a message.

Negative

rows < 0

Treat as invalid; re-prompt instead of silent empty output.

rows = 5

Compact trace

Five rows ending with 5 10 15 20 25 — good for dry-runs.

Bad input

Non-numeric input

Bare int(input()) raises ValueError — use try/except first.

Large rows

Wide output

Row 10 has 10 values up to 100 — use fixed-width formatting for readability.

🎯 Practice Problems

Try these variations to lock in the pattern.

1. Compare with Program 48

  • Program 48 uses one loop and running state
  • Program 49 uses nested loops with growing inner bound

2. Change rows

  • Try rows = 4 or rows = 8 in the live preview
  • Same nested loops, different triangle size

3. Next in series

  • Continue with Program 50
  • Build on multiplication patterns

4. Full table variant

  • Change inner loop to j = 1..rows every row
  • Produces a rectangular multiplication grid

Notes

  • Nested loops. Outer: i = 1..rows. Inner: j = 1..i — inner bound grows with each row.
  • print(..., end=" ") stays on the line; print() advances — call it only after the inner loop finishes.
  • Validate rows > 0 for interactive programs; rows = 1 prints a single 1.
  • Total prints = n(n+1)/2 for n rows — time complexity O(n²).

Quick Takeaway: outer i = 1..rows, inner j = 1..i, print(i*j, end=" "), then print().

⏱️ Time and Space Complexity

ProgramTimeExtra space
Nested loops (Examples 1–3)O(n²)O(1)
Total prints for n rowsn(n+1)/2 valuesTriangular number
Wrap Up

🎉 Conclusion

The triangular multiplication pattern is a natural follow-up to Program 48: nested loops, a growing inner bound, and i*j products on each row. Master the fixed-rows version, then try user input and the compact 5-row trace.

Practice the three examples above, then continue to Program 50 for the next pattern in the series.

Inner loop runs j = 1..i — row i always ends with i*i.

💡 Best Practices

✅ Do

  • Outer: for i in range(1, rows + 1):
  • Inner: for j in range(1, i + 1):
  • Print i * j with end=" " per cell
  • Call print() after each inner loop
  • Validate rows > 0 for interactive programs

❌ Don’t

  • Call print() inside the inner loop
  • Use fixed inner bound j <= rows for triangle shape
  • Forget the row break after inner loop
  • Ignore bad console input in user-facing demos
  • Skip the rows=5 dry-run before coding rows=10

Key Takeaways

Knowledge Unlocked

Five things to remember about this multiplication triangle

Print the pattern the beginner-friendly way.

5
Core concepts
02

Outer loop

i = 1..rows

Code
03

Inner loop

j = 1..i

Code
04

Last value

i * i per row

Logic
O 05

Complexity

O(n²) time

Analysis

❓ Frequently Asked Questions

A triangle where row i contains i values: i*1, i*2, ... up to i*i. Row 4 prints 4 8 12 16.
Outer loop sets row i. Inner loop runs j = 1..i and prints i*j for each column.
The last value on row i is i*i. For i = 5, that is 25.
Yes — change the loop limit or read rows from user input with int(input()).
Change inner loop to j = 1..rows every row: for j in range(1, rows + 1)
O(n²) for n rows because total prints are 1+2+...+n = n(n+1)/2.
Program 48 is a 1D powers-of-11 sequence with one loop. Program 49 uses nested loops for a multiplication triangle.
Use fixed-width formatting like print(f"{i*j:4d}", end=" ") so columns line up.
Yes — the inner loop count changes per row (j = 1..i), which requires nested loops.
Use try/except ValueError around int(input()) and validate rows > 0 before printing.

Did you Know? 🔊

On row i, print i products: i*1, i*2, … up to i*i. Total prints = n(n+1)/2 — a triangular number, so time is O(n²).

Continue to Program 50

Move on to the next pattern in the Python number-pattern series.

Program 50 tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

12 people found this page helpful