Shape Rule
i*j products
Row i prints i values: i*1, i*2, …, i*i.

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.
i*j products
Row i prints i values: i*1, i*2, …, i*i.
i = 1..rows
for i in range(1, rows + 1): picks the row multiplier.
j = 1..i
for j in range(1, i + 1): prints each product on the row.
i*i
Each row ends with i*i — row 5 ends with 25.
rows = 3..10
Pick row count and draw the multiplication triangle in the browser.
Complexity
Total prints = n(n+1)/2 — a triangular number.
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().
It bridges Program 48’s single loop to full nested-loop grids — core multiplication-table thinking.
i is the multiplier.
j runs 1..i.
Program 48 is 1D sequence; Program 49 is nested-loop triangle.
Follow Program 48; continue to Program 50 next.
In short: outer i = 1..rows, inner j = 1..i, print(i*j, end=" "), then print().
Given row count rows = 10, print a triangular multiplication pattern — row i shows i products from i*1 to i*i.
# rows = 10
//1
//2 4
//3 6 9
//4 8 12 16
//5 10 15 20 25
// ... up to row 10 | Item | Type | Description |
|---|---|---|
rows | int | How many triangle rows to print. |
i (outer) | int | Row multiplier — runs from 1 to rows. |
j (inner) | int | Column index — runs from 1 to i on each row. |
| Cell value | int | i * j — last value on row i is i*i. |
for i from 1 to rows:
for j from 1 to i:
print i * j
print newline | Approach | Idea | Best for |
|---|---|---|
| Nested loops | i*j with inner j = 1..i | Learning and interviews |
| User-input rows | rows = int(input()) | Flexible row count |
| Aligned formatting | print(f"{i*j:4d}", end=" ") | Aligned columns for larger rows |
| Full table variant | Inner loop j = 1..rows every row | Rectangular multiplication grid |
| Goal | Pattern |
|---|---|
| Outer loop | for i in range(1, rows + 1): |
| Inner loop | for j in range(1, i + 1): |
| Print product | print(i * j, end=" ") |
| End row | print() |
| Last value on row i | i * i (e.g. row 5 ends with 25) |
| Full table tweak | Change inner to j <= rows |
| Program 48 contrast | Program 48 is 1D sequence; Program 49 is nested-loop triangle |
Same triangle — three ways to set row count and format output.
rows = 10Hard-coded height for demos
int(input())Read row count from console
rows = 5Quick dry-run on paper
{i*j,4}Fixed-width for readability
i * jProduct of row and column
Reach for this pattern when teaching nested loops, multiplication tables, and growing inner bounds.
Natural follow-up after Program 48’s single loop — introduces nested loops with changing inner bounds.
Row i is the i-times table — visual bridge to arithmetic grids.
Total prints = n(n+1)/2 — classic nested-loop complexity example.
Compare Program 48 (1D sequence) and Program 50 (next in series) next.
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.
Choose row count between 3 and 10 and draw the multiplication triangle in the browser.
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.
Print ten rows of the multiplication triangle with nested loops and i*j products.
rows = 10Hard-coded height — outer loop picks row i, inner loop prints i*j.
rows = 10
for i in range(1, rows + 1):
for j in range(1, i + 1):
print(i * j, end=" ")
print() 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.
Read row count with int(input()) and use aligned formatting.
Read rows with int(input()) and print a neatly aligned triangle.
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() Same nested-loop core as Example 1; only the source of rows changes. The triangle grows or shrinks based on user input.
Smaller row count for quick tracing on paper or in interviews.
rows = 5Use rows = 5 to trace both loops quickly before scaling to 10 rows.
rows = 5
for i in range(1, rows + 1):
for j in range(1, i + 1):
print(i * j, end=" ")
print() 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.
Set rows = 10 or read from user input — controls triangle height.
for i in range(1, rows + 1): — on each row, i is the base multiplier.
for j in range(1, i + 1): prints i*j with end=" ".
print() after the inner loop finishes each row.
Total prints = n(n+1)/2 — O(n²) time, O(1) extra memory.
i = 4Trace inner-loop columns j on row 4 — which product prints for each cell.
j | i*j | Prints |
|---|---|---|
1 | 4*1 | 4 |
2 | 4*2 | 8 |
3 | 4*3 | 12 |
4 | 4*4 | 16 |
Full row 4 output: 4 8 12 16. Row 5 would end with 25 because the last product is 5*5.
Where this tiny pattern (and its loop structure) shows up beyond the homework prompt.
Inner bound grows with outer index — classic nested-loop exercise.
Example: trace row i = 4 in the walkthrough table.
Row i is the i-times table — visual arithmetic bridge.
Example: row 5 ends with 25 = 5*5.
Practice print(..., end=" ") vs print() — multiple values per row vs row breaks.
Example: put print() inside the inner loop by mistake.
Total prints = n(n+1)/2 — links loops to summation formulas.
Example: 10 rows print 55 values total.
Growing inner bound makes O(n²) concrete — count prints for n rows.
Example: 5 rows = 1+2+3+4+5 = 15 prints.
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.
Why this pattern earns a permanent spot in beginner Python courses.
Wrong inner bounds show up immediately as a broken triangle.
Each row is a mini multiplication table — not abstract loop drill.
Change rows, use fixed-width format, or switch to full rectangular table.
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.
Small habits that keep number-pattern code clean.
Row i prints exactly i values — use j <= i.
try/except ValueErrorAvoid using uninitialized rows when the user types letters instead of a number.
Only call print() after the inner loop finishes the row.
Use f"{i*j:4d}" for aligned columns on larger rows.
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.
Mistakes that commonly break triangular multiplication patterns.
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.
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.
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.
All products print on one long line without row breaks.
→ Add print() after each inner loop completes.
int(input())Letters or empty input raise ValueError with bare int(input()).
→ Catch ValueError and re-prompt on failure.
Check these inputs before calling the solution done.
Output is just 1 on one line.
Outer loop never runs — print nothing or show a message.
rows < 0Treat as invalid; re-prompt instead of silent empty output.
Five rows ending with 5 10 15 20 25 — good for dry-runs.
Bare int(input()) raises ValueError — use try/except first.
Row 10 has 10 values up to 100 — use fixed-width formatting for readability.
Try these variations to lock in the pattern.
j = 1..rows every rowi = 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.rows > 0 for interactive programs; rows = 1 prints a single 1.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().
| Program | Time | Extra space |
|---|---|---|
| Nested loops (Examples 1–3) | O(n²) | O(1) |
| Total prints for n rows | n(n+1)/2 values | Triangular number |
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.
for i in range(1, rows + 1):for j in range(1, i + 1):i * j with end=" " per cellprint() after each inner looprows > 0 for interactive programsprint() inside the inner loopj <= rows for triangle shapePrint the pattern the beginner-friendly way.
i * j per cell
Definitioni = 1..rows
Codej = 1..i
Codei * i per row
LogicO(n²) time
AnalysisOn 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²).
Move on to the next pattern in the Python number-pattern series.
12 people found this page helpful