Shape Rule
digit i repeats rows − i + 1 times
Row 1 prints 11111, row 2 prints 2222, and so on until the last row prints a single digit.

The shrinking repeating number pattern teaches how a changing inner-loop start value controls row width. This tutorial covers the shape rule, loop structure, a live preview, algorithm steps, worked PHP examples, edge cases, and complexity.
digit i repeats rows − i + 1 times
Row 1 prints 11111, row 2 prints 2222, and so on until the last row prints a single digit.
Rows
for ($i = 1; $i <= $rows; $i++) walks each line as the digit increases from 1 to $rows.
Digits
for ($j = $i; $j <= $rows; $j++) prints digit $i exactly $rows − $i + 1 times on that row.
Same line / next line
Repeated digits use echo $i; end each row with echo PHP_EOL;.
1–20 rows
Pick a row count and draw the shrinking repeating number pattern instantly in the browser.
Complexity
Total digit prints still = n(n+1)/2; extra memory stays O(1).
A shrinking repeating number pattern repeats the row digit on each line, but the row becomes shorter as i increases. With rows = 5, the output is 11111, 2222, 333, 44, 5.
In PHP you solve it with two nested for loops: the outer loop picks the digit, the inner loop runs from $i to $rows and repeats it with echo $i;, then echo PHP_EOL; moves to the next line.
It is a great follow-up after growing and inverted repeating patterns. Once you see how the inner-loop start controls width, many number triangles become predictable.
On row i, print digit i exactly rows − i + 1 times.
Outer picks the digit; inner controls how many times it repeats.
echo $i in the inner loop; echo PHP_EOL; after.
Compare Program 9 (growing repeats) and Program 11 (inverted triangle).
In short: for each row i from 1 to rows, repeat echo $i for j from i to rows, then call echo PHP_EOL;.
Given a positive integer rows, print a shrinking repeating number pattern: row i repeats digit i exactly rows − i + 1 times, with the outer loop counting from 1 up to rows.
// First 5 rows (conceptual shape)
// 11111
// 2222
// 333
// 44
// 5 | Item | Type | Description |
|---|---|---|
rows | int | Number of triangle lines to print (typically ≥ 1). |
| Printed output | text | Each row repeats one digit; row i has rows − i + 1 copies of i, so the first row is widest. |
for i from 1 to rows:
for j from i to rows:
print i (no newline)
print newline | Approach | Idea | Best for |
|---|---|---|
| Nested loops | Outer digit + inner repeats | Learning and interviews |
str_repeat((string) $i, $rows - $i + 1) in inner loop | Print a full repeated row with str_repeat | Leaner C style once loops are understood |
| Goal | Pattern |
|---|---|
| Walk each row | for ($i = 1; $i <= $rows; $i++) |
Repeat digit i | for ($j = $i; $j <= $rows; $j++) echo $i; |
| End the row | echo PHP_EOL; |
| One-line row shortcut | str_repeat((string) $i, $rows - $i + 1) repeated per row |
| Program 11 variant | for ($j = 1; $j <= $i; $j++) echo $i; (Program 9 ascending repeats) |
Same pattern — different ways to emit characters.
same linePrints a digit without moving to the next line
new lineEnds the current row after all digits are printed
one digitWrites digit i when i is 1..9 — no format string
loops firstMaster nested loops before the str_repeat shortcut
Reach for this pattern when teaching how inner-loop bounds control row width.
Most PHP pattern series start here before pyramids and diamonds.
Outer/inner bound practice with an immediate visual check.
Combine loops with fgets(STDIN) for a flexible row count.
Compare Program 9 (1, 22, 333, …) and Program 11 (55555, 4444, …) 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 1 and 20 and draw the shrinking repeating number pattern in the browser.
Three complete PHP programs — fixed row count, CLI input, and a str_repeat shortcut. Click View Output to reveal sample console results.
Print five rows of the shrinking repeating number pattern with nested loops.
rows = 5Hard-coded height — outer picks digit, inner runs from i to rows.
<?php
$rows = 5;
for ($i = 1; $i <= $rows; $i++) {
for ($j = $i; $j <= $rows; $j++) {
echo $i;
}
echo PHP_EOL;
} When i = 1, the inner loop runs from 1 to 5 and prints 11111. When i = 2, it prints 2222, and so on until i = rows prints a single 5. echo PHP_EOL; after the inner loop starts the next row.
Let the user choose the height at runtime.
Read the row count with (int) trim(fgets(STDIN)) (check is_numeric() in real apps).
<?php
echo "Enter the number of rows: ";
$rows = (int) trim(fgets(STDIN));
for ($i = 1; $i <= $rows; $i++) {
for ($j = $i; $j <= $rows; $j++) {
echo $i;
}
echo PHP_EOL;
} Same nested-loop core as Example 1; only the source of rows changes. Non-numeric input casts to 0 without validation — check is_numeric(trim($line)) in safer labs.
Same shape without an explicit inner repeat loop.
str_repeat((string) $i, $rows - $i + 1)Build each row with str_repeat((string) $i, $rows - $i + 1), then end with echo PHP_EOL;.
<?php
$rows = 5;
for ($i = 1; $i <= $rows; $i++) {
echo str_repeat((string) $i, $rows - $i + 1) . PHP_EOL;
} str_repeat((string) $i, $rows - $i + 1) creates a string of repeated digit i. Great once you understand the nested-loop idea; keep the two-loop version for exams that ask you to show both bounds.
Set $rows = 5; and use fgets(STDIN) when reading input from the terminal.
for ($i = 1; $i <= $rows; $i++) picks the digit; the inner loop prints it $rows - $i + 1 times.
for ($j = $i; $j <= $rows; $j++) repeats digit $i with echo $i; as the row shrinks.
echo PHP_EOL; ends the row so the next outer iteration starts fresh.
Total digit prints: 1+2+…+n = n(n+1)/2 — O(n²) time, O(1) extra memory.
rows = 4Trace each outer-loop value of i and count how many times the inner loop prints digit i.
i | Inner j range | Repeats | Printed row |
|---|---|---|---|
1 | 1..4 | 4 | 1111 |
2 | 2..4 | 3 | 222 |
3 | 3..4 | 2 | 33 |
4 | 4..4 | 1 | 4 |
Total digit prints: 1 + 2 + 3 + 4 = 10 = 4×5/2.
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 j <= i and watch the shape change.
Foundation for inverted, pyramid, diamond, and hollow variants.
Example: change inner bound to j <= i for growing repeats (Program 9).
Practice echo vs PHP_EOL without complex math.
Example: put echo PHP_EOL; inside the inner loop by mistake.
Swap digits for letters, stars, or spaced output once the loop works.
Example: use echo $i . " "; for spaced repeated digits on each row.
Triangular totals make O(n²) concrete for beginners.
Example: count printed digits for n = 10 still → 55.
Pair the pattern with fgets(STDIN) 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 C 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: learn the nested-loop version first; treat str_repeat((string) $i, $rows - $i + 1) as a polish shortcut afterward.
Small habits that keep number-pattern code clean.
Use rows (or n) and keep i/j for row/column — or rename to row/col.
Avoid crashes when the user types letters instead of a number.
Only call echo PHP_EOL; after the inner loop finishes the row.
for ($j = $i; $j <= $rows; $j++) with echo $i; is the key to shrinking width.
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 echo PHP_EOL; inside the inner loop.
Mistakes that commonly break shrinking repeating number patterns.
Each repeated digit lands on its own line — you get a column, not a triangle.
→ Use echo $i for repeats; echo PHP_EOL; only after the inner loop.
j <= i grows repeats; j = 1 with wrong bound prints a rectangle.
→ For this shape, keep for ($j = $i; $j <= $rows; $j++).
Omitting echo PHP_EOL; glues every repeat onto one endless line.
→ Always end the row after the inner loop.
Letters or empty input throw undefined rows.
→ Check is_numeric(trim($line)) and re-prompt on failure.
Switching to i = 0 without adjusting the inner bound prints an empty first row or wrong counts.
→ If 0-based, print i with wrong inner bound (e.g. j <= i + 1).
Check these inputs before calling the solution done.
Output is just 1 on one line.
Outer loop never runs — print nothing or show a message.
rows < 0Treat as invalid; re-prompt instead of silent empty output.
Output grows as n²/2 characters — fine for labs, noisy for huge n.
Unchecked CLI leaves rows unset — call is_numeric(trim($line)) first.
Use j = i so row width shrinks as i grows.
Try these variations to lock in the pattern.
j from 1 to i (see Program 9)1, 22, 333, …rows down to 1is_numeric() until $rows >= 1echo $i between repeated digitsn(n+1)/2 — hence O(n²) time.echo $i; stays on the line; echo PHP_EOL; advances — mix them carefully.rows > 0 for interactive programs; rows = 1 should print a single 1.Quick Takeaway: outer loop picks the digit, inner loop runs from i to rows, then break the line — that is the whole pattern.
| Program | Time | Extra space |
|---|---|---|
| Nested loops (Examples 1–2) | O(rows²) | O(1) |
str_repeat((string) $i, $rows - $i + 1) (Example 3) | O(rows²) | O(rows) per row string (temporary) |
The shrinking repeating number pattern is a compact nested-loop exercise: digit increases each row while repeat count shrinks. Master the classic two-loop version, then optionally shorten rows with str_repeat((string) $i, $rows - $i + 1).
Practice the three examples above, then continue to Program 13 for the alternating zigzag number triangle.
Row i repeats digit i exactly rows - i + 1 times — keep echo $i for each copy and echo PHP_EOL; for the break.
i before codingecho $i for repeats and echo PHP_EOL; after each rowrows ≥ 1 for interactive programsis_numeric() before using $rowsecho PHP_EOL; inside the inner repeat loopj = 1 when you meant Program 9 insteadrows = 1 edge casePrint the pattern the beginner-friendly way.
Row i repeats digit i (rows-i+1) times
DefinitionPicks the digit each row
CodeRuns from i to rows
CodeEnds each row
I/OO(n²) time
AnalysisRow digit i repeats rows − i + 1 times. The outer loop counts up from 1, while the inner loop runs from i to rows, so each row shrinks — still O(n²) total prints.
Next up — alternating ascending/descending rows in Program 13.
12 people found this page helpful