Shape Rule
Right-aligned triangle
Row i prints rows down to i, with indentation spaces before the numbers.

The right-aligned decreasing triangle prints 5, then 5 4, then 5 4 3, … — a natural follow-up after Program 35’s continuous counter triangle. This tutorial covers indentation loops, decreasing sequences, fixed-width formatting, nested loops, a live preview, worked JavaScript examples, edge cases, and complexity.
Right-aligned triangle
Row i prints rows down to i, with indentation spaces before the numbers.
i = rows..1
for (let i = rows; i >= 1; i--) — descending outer loop, one row per iteration.
1..i-1
for (let j = 1; j < i; j++) — appends " " for right alignment.
:2d format
for (let j = rows; j >= i; j--) then line += String(j).padStart(2, " ").
3–7 rows
Pick a row count and draw the right-aligned decreasing triangle in the browser.
Complexity
Total prints = n(n+1)/2 — work scales as n².
A right-aligned decreasing number triangle prints a sequence that starts at rows on every row and counts down to i: 5, then 5 4, then 5 4 3, and so on. With rows = 5, shorter rows shift right thanks to an indentation loop.
In JavaScript you use three nested loops: append " " while j < i, then line += String(j).padStart(2, " ") for j = rows..i, then console.log(line).
It combines two inner loops — one for spaces, one for numbers — a step after Program 35’s continuous counter pattern.
Decreasing sequence.
j < i spaces.
Fixed-width columns.
Follow Program 35; continue to Program 37 next.
In short: outer i = rows..1, indent j = 1..i-1 with " ", numbers j = rows..i with padStart(2), then console.log(line).
Given rows = 5, print a right-aligned decreasing triangle: indentation spaces while j < i, then numbers from rows down to i with fixed-width formatting.
# rows = 5
# 5
# 5 4
# 5 4 3
# 5 4 3 2
# 5 4 3 2 1 | Item | Type | Description |
|---|---|---|
rows | int | Triangle height and starting number for each row. |
i | int | Outer loop — current row limit (rows down to 1). |
j | int | Indent loop (1..i-1) or number loop (rows..i). |
for i from rows down to 1:
for j from 1 to i-1: append 2 spaces
for j from rows down to i: append j with padStart(2)
console.log(line) | Approach | Idea | Best for |
|---|---|---|
| Fixed rows | 5, 5 4, … | Learning and interviews |
| User-input rows | parseInt(prompt(...), 10) | Configurable triangle size |
| Compact trace | rows = 3 on paper first | Debugging loop bounds |
| Goal | Pattern |
|---|---|
| Outer loop | for (let i = rows; i >= 1; i--) |
| Indent loop | for (let j = 1; j < i; j++) line += " " |
| Number loop | for (let j = rows; j >= i; j--) |
| Print number | line += String(j).padStart(2, " ") |
| End the row | console.log(line) |
| User input | parseInt(prompt(...), 10) |
Same right-aligned decreasing triangle — different ways to control the row count.
i = rows..1Descending row limit
j < iTwo spaces per step
j = rows..iDecreasing sequence
padStart(2)Fixed-width columns
Reach for this pattern when teaching dual inner loops, decreasing sequences, and right-aligned console output.
Natural follow-up — replaces the continuous counter with a per-row decreasing sequence and a separate indent loop.
Practice separating space printing from number printing before tackling more complex shapes.
Combine loops with prompt() and Number.isFinite for flexible row counts.
Compare Program 35 (incremental counter) and Program 37 (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 dual inner loops, formatted output, and O(n²) thinking.
Choose a row count between 3 and 7 and draw the right-aligned decreasing triangle in the browser.
Three complete JavaScript programs — fixed rows, user input, and a smaller trace demo. Click View Output to reveal sample console results, or Try it Yourself to run the code live.
Print five rows of the right-aligned decreasing triangle with indent and number loops.
rows = 5Hard-coded row count — ideal for first demos and screenshots.
const rows = 5;
for (let i = rows; i >= 1; i--) {
let line = "";
for (let j = 1; j < i; j++) {
line += " ";
}
for (let j = rows; j >= i; j--) {
line += String(j).padStart(2, " ");
}
console.log(line);
} When i = 5, the indent loop appends four space pairs, then 5. When i = 1, no indentation — output 5 4 3 2 1 with fixed-width columns.
Read the row count with prompt() and parseInt() instead of hard-coding 5.
Read rows with prompt() and parseInt() instead of hard-coding 5.
const rowsInput = prompt("Enter rows:");
const rows = parseInt(rowsInput, 10);
if (!Number.isFinite(rows) || rows < 1) {
console.log("Please enter a positive integer.");
} else {
for (let i = rows; i >= 1; i--) {
let line = "";
for (let j = 1; j < i; j++) {
line += " ";
}
for (let j = rows; j >= i; j--) {
line += String(j).padStart(2, " ");
}
console.log(line);
}
} Same dual inner-loop core as Example 1; only rows comes from user input instead of being hard-coded as 5. Non-numeric input yields NaN with bare parseInt(prompt(), 10) — validate with Number.isFinite for safer labs.
Run with rows = 3 to trace every row on paper before scaling up.
rows = 3Same indent and number loops with a smaller row count for quick tracing.
const rows = 3;
for (let i = rows; i >= 1; i--) {
let line = "";
for (let j = 1; j < i; j++) {
line += " ";
}
for (let j = rows; j >= i; j--) {
line += String(j).padStart(2, " ");
}
console.log(line);
} Only rows changes from 5 to 3 — the indent and number loops stay identical. Trace i = 3, 2, 1 on paper to see how indentation shrinks each row.
No imports needed for fixed rows; use prompt() when reading. Set loop variables i, j with rows = 5.
for (let i = rows; i >= 1; i--) — descending outer loop; row limit shrinks each iteration.
for (let j = 1; j < i; j++) — appends " " for right alignment.
for (let j = rows; j >= i; j--) then line += String(j).padStart(2, " ") — decreasing sequence.
console.log(line) ends the row after both inner loops finish.
Total numbers = n(n+1)/2 — O(n²) time, O(1) extra memory.
rows = 5Trace each outer-loop value of i, indentation steps, numbers printed, and full row output.
i | Indent steps | Numbers printed | Row output |
|---|---|---|---|
5 | 4 | 5 | 5 |
4 | 3 | 5, 4 | 5 4 |
3 | 2 | 5, 4, 3 | 5 4 3 |
2 | 1 | 5, 4, 3, 2 | 5 4 3 2 |
1 | 0 | 5, 4, 3, 2, 1 | 5 4 3 2 1 |
Indent steps per row = i - 1 — zero when i = 1. Numbers per row = rows - i + 1.
Where this tiny pattern (and its loop structure) shows up beyond the homework prompt.
Clearest visual proof that outer and inner bounds interact.
Example: remove the indent loop and watch the triangle snap left.
Foundation for right-aligned variants with separate space and number loops.
Example: compare with Program 35 (incremental counter) and Program 37 next.
Practice padStart(2) formatting and fixed-width columns.
Example: change padStart(2) to {0,3} for wider spacing on large row counts.
Add two-space indent groups once the three-loop structure works.
Example: use a single space instead of " " and watch columns drift.
Triangular totals make O(n²) concrete for beginners.
Example: count printed numbers for rows = 5 — total is 1+2+3+4+5 = 15.
Pair the pattern with Number.isFinite and positive-row validation.
Example: reject rows <= 0 and re-prompt.
Pro Tip: when an interviewer asks for patterns, explain the 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 JavaScript courses.
Wrong bounds show up immediately as a broken staircase.
Only loops and console output — no arrays or math libraries.
Invert, center, hollow, or change the fill character with small edits.
Streaming output needs no storage beyond loop counters.
Pro Tip: trace i and both j loops on paper for rows = 3 before coding — watch how indent steps shrink each row.
Small habits that keep number-pattern code clean.
Indent loop (j < i) and number loop (j = rows..i) must run in order before console.log(line).
Number.isFiniteAvoid undefined behavior when the user types letters instead of a number.
Only call console.log(line) after both inner loops finish the row.
Write the decreasing sequence for each i before coding the number loop.
Trace i = 1..3 on paper before coding the full rows = 5 demo.
Pro Tip: if the output is a vertical list of single digits per line, you almost certainly put console.log(line) inside an inner loop.
Mistakes that commonly break right-aligned decreasing triangles.
Each digit lands on its own line — you get a column, not a triangle.
→ Use line += String(j).padStart(2, " "); console.log(line) only after both inner loops.
Without for (let j = 1; j < i; j++), every row starts at the left margin.
→ Run the indent loop before the number loop on every row.
Single spaces instead of " " break column alignment with padStart(2).
→ Print two spaces per indent step to match the fixed-width number columns.
Plain line += j makes multi-digit values crowd earlier columns.
→ Use line += String(j).padStart(2, " ") for consistent column width.
parseInt(prompt())Letters or empty input yield NaN with bare parseInt(prompt(), 10).
→ Validate with Number.isFinite and re-prompt on failure.
Check these inputs before calling the solution done.
Output is just 1 with leading spaces — one value, one row.
Outer loop never runs when rows < 1 — print nothing or show a message.
rows < 1Treat as invalid; re-prompt instead of silent empty output.
Two rows: 1 and 2 3.
Bare parseInt(prompt(), 10) yields NaN on bad input — validate with Number.isFinite first.
Total numbers = rows(rows+1)/2 — grows quadratically with rows.
Try these variations to lock in the pattern.
ki prints rows down to ii - 1rows >= 1 after reading inputi = rows..1. Indent loop j = 1..i-1 appends " ". Number loop j = rows..i prints padStart(2).line += String(j).padStart(2, " ") stays on the line; console.log(line) advances — mix them carefully.rows >= 1 for interactive programs; rows = 1 prints a single 1.i - 1 — compare with Program 35 where a continuous counter replaces the per-row sequence.Quick Takeaway: outer i = rows..1, indent j = 1..i-1 with " ", numbers j = rows..i with padStart(2), then console.log(line).
| Program | Time | Extra space |
|---|---|---|
| Nested loops (Examples 1–3) | O(n²) | O(1) |
| Smaller demo (Example 3) | O(n²) | O(1) |
The right-aligned decreasing number triangle is a compact lesson in dual inner loops and formatted output: indent with " ", print rows down to i with line += String(j).padStart(2, " "), and end each row with console.log(line). Master the fixed-rows version, then try user input and a smaller trace demo.
Practice the three examples above, then continue to Program 37 for the next pattern in the series.
Run the indent loop before the number loop — validate rows when reading from the console.
for (let i = rows; i >= 1; i--) in the outer loopfor (let j = 1; j < i; j++) line += " "line += String(j).padStart(2, " ") for j = rows..iparseInt(prompt(), 10) with Number.isFiniteconsole.log(line) inside an inner loop" " for indentationrows = 1 edge casePrint the pattern the beginner-friendly way.
Decreasing seq
Definitionj < i spaces
CodeFixed width
Codeconsole.log(line) after both inner loops
O(n²) time
AnalysisEach row starts from rows and counts down to i. An indentation loop appends two spaces per step (j = 1..i-1), then String(j).padStart(2, " ") keeps number columns aligned.
Move on to the palindrome number triangle in the JavaScript number-pattern series.
12 people found this page helpful