JavaScript Number Triangle Pattern (Bidirectional)

Beginner
5 min read
Updated: Sep 2026
3 programs
Live preview

What Is This Pattern?

A bidirectional number triangle prints a repeated digit on each shrinking row — digits rise (1, 2, 3) then mirror down (2, 1).

Remember
Rule: row i repeats val, length = rows − i + 1
      val = i if i < rows − 1
          else rows + 1 − i

11111
2222
333
22
1     ← rows = 5

Shrinking length plus a mapped digit — a clear follow-up after the centered pyramid in Program 24.

How to Solve It

Outer i = 1..rows; pick the row digit; inner j = i..rows repeats that digit.

MethodIdeaBest for
if/else mappingRise then rows + 1 − iLearning, interviews
prompt + ternarySame loops; generalize for any rowsInteractive practice
Spaced digitsline += val + " "Readable output

Pseudocode

Pseudocode
for i from 1 to rows:
    if i < rows - 1:
        val = i
    else:
        val = rows + 1 - i
    line = ""
    for j from i to rows:
        line += val
    print line (with newline)

Cheat sheet

GoalPattern
Set rowsconst rows = 5;
Outer loopfor (let i = 1; i <= rows; i++)
Pick digitconst val = i < rows - 1 ? i : rows + 1 - i;
Shrink rowfor (let j = i; j <= rows; j++) line += val;
End rowconsole.log(line);
Spacedline += val + " ";

Printing Numbers vs Starting a New Line

APIEffectUse for
line += valStays on the same rowEach repeated digit
console.log(line)Ends the lineAfter the inner loop

Build the row with +=, then break once with console.log. Putting console.log inside the inner loop prints one digit per line.

Live Preview

Change the row count and the bidirectional triangle updates instantly.

Whole numbers from 1 to 9. Tap a chip or type a value — the preview redraws as you go.

Live result rows = 5 · digits = 15
11111
2222
333
22
1

Worked Walkthrough — rows = 4

Trace each i, the mapped digit, and how many times it repeats.

ivalRepeatsPrinted row
11 (i < 3)4×1111
22 (i < 3)3×222
32 (4 + 1 − 3)2×22
41 (4 + 1 − 4)1×1

The switch happens when i >= rows − 1 — that is when the digit starts mirroring down.

JavaScript Programs

Three complete programs: fixed rows = 5, prompt input, and spaced digits. Use View Output for sample results, or Try It Yourself to edit and run in the playground.

Example 1 — Fixed rows = 5

Hard-coded height — if/else picks the digit; the inner loop shrinks each row.

JavaScript
const rows = 5;

for (let i = 1; i <= rows; i++) {
  let line = "";
  for (let j = i; j <= rows; j++) {
    if (i < 4) {
      line += i;
    } else {
      line += rows + 1 - i;
    }
  }
  console.log(line);
}
Try It Yourself

How It Works

1. Outer rows. i runs from 1 to 5 — one row per value.

2. Shrink. Inner j starts at i, so row length is rows − i + 1.

3. Map digit. When i < 4, print i; otherwise print rows + 1 − i (gives 2, then 1).

Example 2 — prompt Input

Read the row count at runtime; a ternary generalizes the digit mapping for any size.

JavaScript
const rows = parseInt(prompt("Enter rows:"), 10);

if (!Number.isFinite(rows) || rows < 1) {
  console.log("Please enter a positive integer.");
} else {
  for (let i = 1; i <= rows; i++) {
    const val = i < rows - 1 ? i : rows + 1 - i;
    let line = "";
    for (let j = i; j <= rows; j++) {
      line += val;
    }
    console.log(line);
  }
}
Try It Yourself

How It Works

1. Prompt and parse. Convert the answer with parseInt(..., 10).

2. Validate first. Reject NaN or non-positive values before looping.

3. General mapping. i < rows − 1 ? i : rows + 1 − i replaces the hard-coded i < 4.

Example 3 — Spaced Digits

Keep rows = 5 but append a space after each digit for easier reading.

JavaScript
const rows = 5;

for (let i = 1; i <= rows; i++) {
  const val = i < rows - 1 ? i : rows + 1 - i;
  let line = "";
  for (let j = i; j <= rows; j++) {
    line += val + " ";
  }
  console.log(line);
}
Try It Yourself

How It Works

1. Same structure. Outer loop, mapping, and shrinking inner loop match Example 2.

2. Only append changes. Use line += val + " " instead of line += val.

3. Same shape. Row lengths and digit values are unchanged — only spacing differs.

Edge Cases & Pitfalls

Check these before calling the solution done.

j = 1

Rows do not shrink

Starting the inner loop at j = 1 keeps every row length rows. Use j = i.

hard 4

Hard-coded threshold

i < 4 only fits rows = 5. Prefer i < rows − 1 for other sizes.

log inside

Vertical digits

If console.log is inside the inner loop, each digit lands on its own line. Append with +=; log only after the loop.

rows = 1

Single digit

Output is just 1 — the mirror branch still yields rows + 1 − i = 1.

rows ≤ 0

Empty output

The outer loop never runs. Guard prompt input with rows >= 1.

NaN input

Validate parseInt

Letters or empty prompt yield NaN — check Number.isFinite(rows) && rows >= 1.

Time and Space Complexity

ProgramTimeExtra space
Examples 1–3O(n²)O(n) for the current line string

Total digits = n + (n−1) + … + 1 = n(n+1)/2 → O(n²).

Key Takeaways

  • Rule: shrink with j = i..rows; map digit up then down.
  • Mapping: val = i < rows − 1 ? i : rows + 1 − i.
  • Write vs log: line += val builds; console.log(line) breaks.
  • Complexity: O(n²) for n rows.

One line: shrink the row from the left, and flip the printed digit after the peak with rows + 1 − i.

Frequently Asked Questions

For i = 5 and rows = 5, the condition i < rows − 1 is false, so the program uses rows + 1 − i, which equals 1.
Because the inner loop runs from j = i to rows. As i increases, the inner loop executes fewer times.
Digits rise (1, 2, 3) on early rows then mirror down (2, 1) on the last rows via the rows + 1 − i mapping.
line += val repeats the digit on the same line. console.log(line) ends the row after the inner loop finishes.
A single inner loop with a digit mapping keeps the shrinking row logic in one place.
Use val = i < rows − 1 ? i : rows + 1 − i (see Example 2).
O(n²) for n rows because total prints are triangular (n + (n−1) + … + 1).
Use parseInt(prompt(...), 10) and check Number.isFinite(rows) && rows >= 1 so bad input does not produce NaN.
Only one row prints — a single 1.

Did you know?

This pattern prints repeated digits per row. The inner loop runs from j = i to rows, shrinking each row. The row digit is i for the first half, then switches to rows + 1 - i to produce 22 and 1.

Next: Diagonal Asterisk Pattern

Continue with the next pattern in the JavaScript number-pattern series.

Program 26 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