A reverse ascending number triangle grows digits from the left. The first row shows only the peak digit; each next row adds one more number on the left until the last row shows 1..rows.
Unlike Program 5 (outer up, print 1..i), this pattern counts the outer loop down and prints i..rows so digits accumulate on the left.
Approach
How to Solve It
Outer loop from rows down to 1. Inner loop from current i up to rows. Print each digit, then end the line.
Method
Idea
Best for
Nested loops
Outer down, inner i..rows
Learning, interviews, demos
Compact trace
Same logic with rows = 3
Quick dry-runs on paper
Pseudocode
Pseudocode
for i from rows down to 1:
for j from i to rows:
print j
print newline
Cheat sheet
Goal
Pattern
Outer (start moves left)
for (i = rows; i >= 1; i--)
Inner (end fixed)
for (j = i; j <= rows; j++)
Print digit
cout << j;
End the row
cout << "\n";
Digits on outer i
rows - i + 1
Printing Numbers vs Starting a New Line
API
Effect
Use for
cout << j
Stays on the same line
Each digit
cout << "\n"
Ends the line
After the inner loop
Print digits without a newline, then end the row once.
Try it
Live Preview
Change the row count and the reverse ascending triangle updates instantly.
Use rows from 1 to 9. Tap a chip or type a value — the preview redraws as you go.
Live result5 rows · 15 digits
5
45
345
2345
12345
Trace
Worked Walkthrough
Trace three outer values when rows = 5 — watch the start digit move left.
Outer i
Inner j
Prints
5
5..5
5
3
3..5
345
1
1..5
12345
The inner end stays fixed at rows; only the start moves left as i decreases.
Code
C++ Programs
Three complete programs: fixed rows = 5, cin input, and a compact rows = 3 demo. Use View Output to reveal sample results.
Example 1 — Fixed rows = 5
Hard-coded height — outer down from 5, inner from i to 5.
C++
#include <iostream>
using namespace std;
int main()
{
int rows = 5;
int i, j;
for (i = rows; i >= 1; i--)
{
for (j = i; j <= rows; j++)
cout << j;
cout << "\n";
}
return 0;
}
Output
5
45
345
2345
12345
How It Works
1. Outer counts down.i starts at rows and moves toward 1 — that is the first digit of each row.
2. Inner fills to the peak.j runs from i to rows, so every row ends on the same peak digit.
3. End the row. Call cout << "\n" only after the inner loop finishes.
Example 2 — User Input Rows
Read the row count at runtime with a simple validation tip.
C++
#include <iostream>
using namespace std;
int main()
{
int rows, i, j;
cout << "Enter the number of rows: ";
cin >> rows;
for (i = rows; i >= 1; i--)
{
for (j = i; j <= rows; j++)
cout << j;
cout << "\n";
}
return 0;
}
Output (when user enters 4)
Enter the number of rows: 4
4
34
234
1234
How It Works
1. Same loop core. Only the source of rows changes from a literal to cin.
2. Entering 4 stops early. You get four rows ending at 1234.
3. Validate in real apps. Prefer checking cin failure and requiring a positive height (tip below).
Safer input tip
if (!(cin >> rows) || rows < 1)
{
cout << "Please enter a positive integer.\n";
return 1;
}
Example 3 — Compact rows = 3
Smaller height for a quick paper trace of both loop bounds.
C++
#include <iostream>
using namespace std;
int main()
{
int rows = 3;
int i, j;
for (i = rows; i >= 1; i--)
{
for (j = i; j <= rows; j++)
cout << j;
cout << "\n";
}
return 0;
}
Output
3
23
123
How It Works
1. Only three rows. Easy to dry-run every i and j value on paper.
2. Same formula. Nothing changes except rows — proving the pattern scales.
3. Left growth still holds. Row 2 prints 23 — start moves left from 3 to 2.
Edge Cases & Pitfalls
Check these before calling the solution done.
Loop direction
Keep the outer loop counting down
Counting up with the same inner bound reprints Program 5’s shape, not this one.
Inner bound
End at rows, not at a shrinking limit
Using j <= i while counting down produces a shrinking triangle instead.
Newlines
Do not put "\n" inside the inner loop
That prints one digit per line and destroys the triangle.
Bad cin
Validate input
Check cin >> rows and require rows >= 1 before the loops.
Analysis
Time and Space Complexity
Program
Time
Extra space
Triangle (Examples 1–3)
O(n²)
O(1)
Digits printed are 1 + 2 + … + n = n(n + 1) / 2 — quadratic in n. Extra memory is only the loop variables.
Remember
Key Takeaways
Rule: outer i = rows..1, inner j = i..rows.
Growth: each row adds one digit on the left until 1..rows.
Break the row: call cout << "\n" only after the inner loop finishes.
Complexity:O(n²) time, O(1) extra space.
One line: count the start digit down from rows, and always print through rows.
Frequently Asked Questions
The outer loop begins at i = rows. The inner loop prints j from i to rows, so the first row prints only that single digit.
When i = 1, the inner loop runs j from 1 to rows — printing 1, 2, 3, 4, 5 on one line.
Each row adds one more digit on the left: for rows=5 you get 5, 45, 345, 2345, 12345.
Program 5 counts the outer loop up and prints 1..i. Program 6 counts the outer loop down and prints i..rows — digits grow from the left instead of the right.
Printing a digit stays on the same line. Printing a newline ends the current row. Digits use cout without a newline; the row break uses cout << "\n" after the inner loop.
O(n²) for n rows because total prints are 1 + 2 + ... + n = n(n+1)/2.
Change the rows literal or read it with cin — see Example 2.
One row prints a single digit 1 — the inner loop runs j from 1 to 1 only once.
🤔
Did you know?
The outer loop starts from rows down to 1, and the inner loop prints i..rows — producing 5, 45, 345, and so on. Total prints still grow as O(n²).