Shape Rule
Palindrome rows
Each row reads the same forwards and backwards — 12321 is a palindrome.

The palindrome number triangle prints 1, 121, 12321, 1234321, 123454321 — a natural step after the diagonal asterisk pattern in Program 26. This tutorial covers ascending and descending inner loops, mirroring, a live preview, algorithm steps, worked JavaScript examples, edge cases, and complexity.
Palindrome rows
Each row reads the same forwards and backwards — 12321 is a palindrome.
i = 1..rows
for (let i = 1; i <= rows; i++) grows the palindrome length each row.
1..i
for (let j = 1; j <= i; j++) prints the left half of each row.
i-1..1
for (let k = i - 1; k >= 1; k--) mirrors without repeating the peak.
3–9 rows
Pick a row count and draw the palindrome triangle instantly in the browser.
Complexity
Total prints grow as n² — row i prints 2i - 1 digits.
A palindrome number triangle prints an ascending sequence then mirrors it back down on the same row. With rows = 5, the output is 1, 121, 12321, 1234321, 123454321.
In JavaScript you use an outer loop for rows, an ascending inner loop j = 1..i, then a descending inner loop k = i-1..1.
It combines two inner loops for symmetry — a step up from Program 26’s single conditional swap.
First inner loop prints ascending digits.
Second loop mirrors without repeating the peak.
Each row reads the same forwards and backwards.
Follow Program 26; continue to Program 28 (0-centered mirror) next.
In short: for each i, append 1..i then i-1..1, then console.log(line).
Given a positive integer rows (e.g. 5), print a palindrome triangle: for each i, print 1..i then i-1..1 on the same line.
# rows = 5 (conceptual shape)
# 1
# 121
# 12321
# 1234321
# 123454321 | Item | Type | Description |
|---|---|---|
rows | int | Number of rows — outer loop runs from 1 to rows. |
i | int | Outer loop — current row; also the peak digit of the palindrome. |
j | int | Ascending loop — prints 1..i (left half). |
k | int | Descending loop — prints i-1..1 (right half). |
for i from 1 to rows:
line = ""
for j from 1 to i:
line += j
for k from i - 1 down to 1:
line += k
console.log(line) | Approach | Idea | Best for |
|---|---|---|
| Two inner loops | 1, 121, 12321, … | Learning and interviews |
| User-input rows | const rows = parseInt(prompt(...), 10) | Flexible console programs |
| Spaced output | line += j + " " | Easier reading for wide rows |
| Goal | Pattern |
|---|---|
| Walk rows | for (let i = 1; i <= rows; i++) |
| Ascending half | for (let j = 1; j <= i; j++) { line += j; } |
| Descending half | for (let k = i - 1; k >= 1; k--) { line += k; } |
| End the row | console.log(line) |
| Spaced digits | line += j + " " / line += k + " " in both loops |
| User input | const rows = parseInt(prompt(...), 10) |
Same palindrome triangle — different ways to control rows and formatting.
i = 1..rowsGrows palindrome length each row
j = 1..iAscending digits
k = i-1..1Mirror without repeating peak
k = i-1Start mirror at i-1, not i
Reach for this pattern when teaching symmetry with two inner loops and palindrome row construction.
Natural follow-up after Program 26 — introduces two inner loops for mirroring.
Outer/inner bound practice with an immediate visual check.
Combine loops with prompt() for a flexible row count.
Compare Program 26 (diagonal asterisk) and Program 28 (0-centered mirror) next.
This is a console teaching pattern — not how you build modern app screens.
Key benefit: one small program that locks in nested loops, output sequencing, and O(n²) thinking.
Choose a row count between 3 and 9 and draw the palindrome number triangle in the browser.
Three complete JavaScript programs — fixed rows, user input, and spaced output variant. Click View Output to reveal sample console results, or Try it Yourself to run the code live.
Print five rows of the palindrome triangle with ascending and descending inner loops.
rows = 5Hard-coded row count — ideal for first demos and screenshots.
const rows = 5;
for (let i = 1; i <= rows; i++) {
let line = "";
for (let j = 1; j <= i; j++) {
line += j;
}
for (let k = i - 1; k >= 1; k--) {
line += k;
}
console.log(line);
} When i = 1, only the ascending loop runs — output 1. When i = 3, append 123 then mirror 21 — output 12321. The second loop starts at i - 1 so the peak digit is not repeated.
Read the row count with prompt() instead of hard-coding 5.
Read rows with prompt() and parseInt(); both inner loops use i as the bound.
const rowsInput = prompt("Enter rows:");
const rows = parseInt(rowsInput, 10);
for (let i = 1; i <= rows; i++) {
let line = "";
for (let j = 1; j <= i; j++) {
line += j;
}
for (let k = i - 1; k >= 1; k--) {
line += k;
}
console.log(line);
} Same two-loop core as Example 1; only the outer bound changes from 5 to rows. The palindrome length grows with each row. Non-numeric input yields NaN with bare parseInt(prompt(), 10) — validate with Number.isFinite for safer labs.
Add a space between digits for easier reading on wide rows.
Keep rows = 5 but append each digit followed by a space in both loops.
const rows = 5;
for (let i = 1; i <= rows; i++) {
let line = "";
for (let j = 1; j <= i; j++) {
line += j + " ";
}
for (let k = i - 1; k >= 1; k--) {
line += k + " ";
}
console.log(line);
} Only the append changes — line += j + " " and line += k + " ". Loop bounds and the k = i - 1 start stay the same as Example 1.
console.log is built in; use prompt() when reading input. Set loop variables i, j, k and rows = 5.
for (let i = 1; i <= rows; i++) — one palindrome row per iteration.
for (let j = 1; j <= i; j++) — prints digits 1..i (left half).
for (let k = i - 1; k >= 1; k--) — mirrors without repeating the peak.
console.log(line) ends the row after both inner loops finish.
Each row mirrors itself — O(n²) time, O(1) extra memory.
rows = 5Trace each outer-loop value of i, the ascending and descending halves, and the full row output.
i | Ascending (j) | Descending (k) | Row output |
|---|---|---|---|
1 | 1 | (none) | 1 |
2 | 1, 2 | 1 | 121 |
3 | 1, 2, 3 | 2, 1 | 12321 |
4 | 1, 2, 3, 4 | 3, 2, 1 | 1234321 |
5 | 1, 2, 3, 4, 5 | 4, 3, 2, 1 | 123454321 |
Row length grows as 2i - 1 digits — total prints = n² for n rows.
Where this tiny pattern (and its loop structure) shows up beyond the homework prompt.
Clearest visual proof that outer and inner bounds interact.
Example: change k = i - 1 to k = i and watch the peak digit repeat.
Foundation for inverted, pyramid, diamond, and hollow variants.
Example: continue to Program 28 for a 0-centered descending mirror variant.
Practice line += vs console.log(line) without complex math.
Example: put console.log(line) inside the inner loop by mistake.
Add spaces between digits once the two-loop structure works.
Example: use line += j + " " in both inner loops.
Triangular totals make O(n²) concrete for beginners.
Example: count printed digits for rows = 5 → 1 + 3 + 5 + 7 + 9 = 25.
Pair the pattern with Number.isFinite and positive-row checks.
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, j, and k on paper for rows = 3 before coding — the mirror starts at i - 1.
Small habits that keep number-pattern code clean.
Use j for ascending and k for descending — do not reuse the same variable for both halves.
prompt()Validate parseInt(prompt(), 10) with Number.isFinite so bad input does not produce NaN.
console.log(line) OutsideOnly call console.log(line) after the inner loop finishes the row.
Mark the ascending half and mirror half for each row before coding.
Trace rows = 3 on paper before coding larger demos.
Pro Tip: if the output is a vertical list of single digits per line, you almost certainly put console.log(line) inside the inner loop.
Mistakes that commonly break palindrome number triangles.
Each digit lands on its own line — you get a column, not a triangle.
→ Use line += j or line += k; console.log(line) only after both inner loops.
Starting k = i repeats the peak digit — e.g. 1221 instead of 121.
→ Use for (let k = i - 1; k >= 1; k--) so the middle digit appears once.
Only the ascending half prints — rows look like 1, 12, 123 instead of palindromes.
→ Add the descending loop for (let k = i - 1; k >= 1; k--) after the ascending loop.
Writing line += i in an inner loop repeats the row number, not the sequence digit.
→ Print j in the ascending loop and k in the descending loop.
Letters or empty input yield NaN from 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 — the mirror loop does not run.
Outer loop never runs — print nothing or show a message.
rows < 0Treat as invalid; re-prompt instead of silent empty output.
Two rows: 1 and 121.
parseInt(prompt(), 10) yields NaN — validate with Number.isFinite first.
Output grows as rows² digits — fine for labs, noisy for huge values.
Try these variations to lock in the pattern.
i == j swapline += j + " " in both loops(char)('a' + j - 1) instead of digits1..i; descending loop prints i-1..1 — start mirror at i - 1, not i.line += stays on the line; console.log(line) advances — mix them carefully.rows > 0 for interactive programs; rows = 1 prints a single 1.line += j + " " in both loops for easier reading on wide rows.Quick Takeaway: outer loop i = 1..rows, ascending j = 1..i, descending k = i-1..1, then console.log(line) after each row.
| Program | Time | Extra space |
|---|---|---|
| Nested loops (Examples 1–3) | O(n²) | O(1) |
| Spaced output (Example 3) | O(n²) | O(1) |
The palindrome number triangle is a compact lesson in symmetry: append ascending 1..i, mirror with descending i-1..1, and end each row with console.log(line). Master the fixed-rows version, then try user input and spaced output.
Practice the three examples above, then continue to Program 28 for the 0-centered descending mirror pattern.
Start the mirror loop at i - 1, not i — validate rows when reading from the console.
for (let i = 1; i <= rows; i++) in the outer loopfor (let j = 1; j <= i; j++)for (let k = i - 1; k >= 1; k--)parseInt(prompt(), 10) with Number.isFinite before using rowsconsole.log(line) inside either inner loopk = i (repeats peak)i instead of j or krows = 1 edge casePrint the pattern the beginner-friendly way.
1..i then i-1..1
DefinitionAscending
CodeMirror
CodeSame both ways
ShapeO(n²) time
AnalysisThis palindrome triangle appends 1..i and then i-1..1 on each row. The second loop mirrors the first, producing outputs like 12321 and 123454321.
Move on to the 0-centered descending mirror number pattern in the JavaScript number-pattern series.
12 people found this page helpful