Unlike Program 57 (top half only), this adds a second outer loop from rows - 1 down to 1 — total lines = 2n - 1.
Approach
How to Solve It
Reuse the same row logic twice: ascend i = 1..rows, then descend i = rows-1..1.
Method
Idea
Best for
Top + bottom
Same i === j / i === k row builder, two outer loops
Classic diamond demos
Compact
Same logic with fewer rows (e.g. 3)
Quick dry-runs
Pseudocode
Pseudocode
function printRow(i):
line = ""
for j from rows down to 1: // left
append i if i === j else " "
for k from 2 to rows: // right
append i if i === k else " "
print line
for i from 1 to rows: // top
printRow(i)
for i from rows-1 down to 1: // bottom
printRow(i)
Cheat sheet
Goal
Pattern
Top half
for (let i = 1; i <= rows; i++)
Bottom half
for (let i = rows - 1; i >= 1; i--)
Left diagonal
for (let j = rows; j >= 1; j--) line += (i === j) ? i : " ";
Right diagonal
for (let k = 2; k <= rows; k++) line += (i === k) ? i : " ";
End the row
console.log(line);
Total lines
2 * rows - 1
Printing Numbers vs Starting a New Line
API
Effect
Use for
line += …
Stays on the same row
Each digit or space
console.log(line)
Ends the current row
After both diagonal halves finish
Append without a newline, then end the row once.
Try it
Live Preview
Change the size and the diagonal diamond updates instantly.
Whole numbers from 1 to 9. Tap a chip or type a value — the preview redraws as you go.
Live resultrows = 5 · 9 lines
1
2 2
3 3
4 4
5 5
4 4
3 3
2 2
1
Trace
Worked Walkthrough
Trace key lines when rows = 5 — top climb, peak, then bottom mirror.
Half
i
Role
Printed row
Top
1
First tip
1
Top
5
Peak (once)
5 5
Bottom
4
First mirror
4 4
Bottom
1
Last tip
1
The bottom loop starts at rows - 1 so the peak line is never printed twice.
Code
JavaScript Programs
Three complete programs: fixed rows = 5, prompt input, and a compact rows = 3 demo. Use View Output for samples, or Try It Yourself to edit and run live.
Example 1 — Fixed rows = 5
Top loop prints the inverse-V; bottom loop mirrors it from rows - 1 down to 1.
JavaScript
const rows = 5;
for (let i = 1; i <= rows; i++) {
let line = "";
for (let j = rows; j >= 1; j--) {
line += (i === j) ? i : " ";
}
for (let k = 2; k <= rows; k++) {
line += (i === k) ? i : " ";
}
console.log(line);
}
for (let i = rows - 1; i >= 1; i--) {
let line = "";
for (let j = rows; j >= 1; j--) {
line += (i === j) ? i : " ";
}
for (let k = 2; k <= rows; k++) {
line += (i === k) ? i : " ";
}
console.log(line);
}
1. Top half builds the inverse-V. Same as Program 57 — digit on i === j and i === k, spaces elsewhere.
2. Bottom half mirrors it. Loop i from rows - 1 down to 1 with identical inner logic.
3. Peak prints once. Starting the bottom at rows - 1 avoids a double middle row.
Example 2 — User Input Rows
Read rows with prompt and validate before drawing.
JavaScript
const rows = parseInt(prompt("Enter number of rows:"), 10);
if (!Number.isFinite(rows) || rows < 1) {
console.log("Please enter a positive integer.");
} else {
for (let i = 1; i <= rows; i++) {
let line = "";
for (let j = rows; j >= 1; j--) {
line += (i === j) ? i : " ";
}
for (let k = 2; k <= rows; k++) {
line += (i === k) ? i : " ";
}
console.log(line);
}
for (let i = rows - 1; i >= 1; i--) {
let line = "";
for (let j = rows; j >= 1; j--) {
line += (i === j) ? i : " ";
}
for (let k = 2; k <= rows; k++) {
line += (i === k) ? i : " ";
}
console.log(line);
}
}
Same top + bottom logic with fewer rows for a quick visual check.
JavaScript
const rows = 3;
for (let i = 1; i <= rows; i++) {
let line = "";
for (let j = rows; j >= 1; j--) {
line += (i === j) ? i : " ";
}
for (let k = 2; k <= rows; k++) {
line += (i === k) ? i : " ";
}
console.log(line);
}
for (let i = rows - 1; i >= 1; i--) {
let line = "";
for (let j = rows; j >= 1; j--) {
line += (i === j) ? i : " ";
}
for (let k = 2; k <= rows; k++) {
line += (i === k) ? i : " ";
}
console.log(line);
}
1. Shrink the size. Only rows changes — still top climb then bottom mirror.
2. Easier to trace. Five lines total — useful while learning the two outer loops.
3. Same peak rule. The widest row still appears only once.
Edge Cases & Pitfalls
Check these before calling the solution done.
Peak skip
Start the bottom loop at rows - 1
Starting at rows duplicates the widest middle line.
Center skip
Right inner loop still starts at k = 2
Same as Program 57 — including k = 1 doubles the center column.
rows = 1
Single-row case
Output is just 1 — the bottom loop never runs.
Bad input
Validate parseInt
Check Number.isFinite(rows) and require rows >= 1 before the loops.
Analysis
Time and Space Complexity
Program
Time
Extra space
Fixed / compact (Examples 1, 3)
O(n²)
O(n) per row string
User input (Example 2)
O(n²)
O(n) per row string
About 2n - 1 lines, each scanning about 2n - 1 positions — still quadratic in n.
Remember
Key Takeaways
Rule: Program 57’s inverse-V on top, then mirror it downward.
Peak once: start the bottom loop at rows - 1.
Break the row: call console.log(line) only after both diagonal halves finish.
Complexity:O(n²) — ~2n lines × ~2n chars.
One line: print the diagonal inverse-V upward, then reuse the same row logic downward from n - 1.
Frequently Asked Questions
The first loop prints the top inverse-V (i = 1..rows). The second prints the bottom half (rows-1 down to 1), mirroring the shape.
Starting at rows would print the middle peak twice. rows-1 skips the line already printed by the top half.
Program 57 prints only the top pyramid. Program 58 adds a second outer loop to mirror the same row logic downward.
line += appends a digit or space on the same row. console.log ends the row after both diagonal halves finish.
Starting at 2 skips the center column already handled by the left loop — avoids a double digit in the middle.
O(n²) for n rows because you print 2n-1 lines, each scanning about 2n positions.
Yes — write a function that builds one row for a given i, then call it from both outer loops.
One line prints a single 1 — the bottom loop does not run.
🤔
Did you know?
Print the Program 57 pyramid for the top half, then mirror with for (let i = rows - 1; i >= 1; i--). Total lines = 2×rows-1 — each row scans about 2×rows-1 positions.