Pattern 19
Java source ↗ Edit this article ↗
Jump to code:
Problem
Given a positive integer n, print the symmetric void: 2n rows, each 2n characters wide. The first row is solid stars. Each following row of the top half removes one star from the inner end of both sides, so a gap opens in the middle and grows by two per row, until the n-th row has a single star at each edge. The bottom half is the top half upside down, so the whole figure is symmetric about its horizontal midline.
Constraints: 1 ≤ n ≤ 50 or so; the output has 4n^2 characters.
Example 1
n = 3
******
** **
* *
* *
** **
******
Six rows of six characters; the gap grows 0, 2, 4 and then shrinks 4, 2, 0.
Example 2
n = 5
**********
**** ****
*** ***
** **
* *
* *
** **
*** ***
**** ****
**********
Rows 5 and 6 are identical, which is what makes the figure mirror-symmetric with an even number of rows.
Reading the pattern
Each row consists of s stars, a gap, and s stars again. Because the width is always 2n, the gap is forced: gap = 2n - 2s = 2(n - s). So a row is completely determined by its star count s, and the pattern is just the sequence of star counts
n, n-1, ..., 2, 1, 1, 2, ..., n-1, n
for rows 0 .. 2n-1. Written as a formula over the row index r (0-based):
- top half (
r < n):s = n - r - bottom half (
r ≥ n):s = r - n + 1
Everything else is bookkeeping. You can implement the two halves as two separate loops that mirror each other, or as one loop over all 2n rows using the formula above. Both are shown. Both return the finished picture as a single String (newline after every row) so main can compare them with expected strings and check structural properties, such as every row being a palindrome, for n up to 20.
Approach 1: Two halves, three loops per row
Intuition. Translate the description literally. For the top half, row i (0-based) has n - i stars on each side and 2i spaces in between. For the bottom half, row i has i + 1 stars on each side and 2(n - i - 1) spaces. Each half is a loop with three inner loops: stars, spaces, stars.
Algorithm.
- For
ifrom0ton - 1: appendn - istars,2ispaces,n - istars, newline. - For
ifrom0ton - 1: appendi + 1stars,2(n - i - 1)spaces,i + 1stars, newline.
static String nestedLoops(int n) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) { // top half: n-i stars each side, 2i spaces
for (int j = 0; j < n - i; j++) sb.append('*');
for (int j = 0; j < 2 * i; j++) sb.append(' ');
for (int j = 0; j < n - i; j++) sb.append('*');
sb.append('\n');
}
for (int i = 0; i < n; i++) { // bottom half: i+1 stars each side, 2(n-i-1) spaces
for (int j = 0; j < i + 1; j++) sb.append('*');
for (int j = 0; j < 2 * (n - i - 1); j++) sb.append(' ');
for (int j = 0; j < i + 1; j++) sb.append('*');
sb.append('\n');
}
return sb.toString();
}
Complexity. Time O(n^2): 2n rows of 2n characters, each appended in constant time. Space O(n^2) for the output; no other memory grows with n.
The duplicated structure is a hint that there is a shorter formulation, but the two-loop version is still worth knowing: when a pattern’s halves follow different rules, two loops is the honest way to write it.
Approach 2: One loop with a star-count formula
Intuition. Compute the star count s for row r with the two-case formula from the analysis, then build the row from three pieces with String.repeat: s stars, 2(n - s) spaces, s stars. The gap is derived from s, so it is impossible for the row width to come out wrong.
Algorithm.
- For
rfrom0to2n - 1: lets = (r < n) ? n - r : r - n + 1. - Let
side = "*".repeat(s). - Append
side, then" ".repeat(2(n - s)), thenside, then a newline.
static String formula(int n) {
StringBuilder sb = new StringBuilder();
for (int r = 0; r < 2 * n; r++) {
int stars = r < n ? n - r : r - n + 1; // n, n-1, ..., 1, 1, ..., n-1, n
String side = "*".repeat(stars);
sb.append(side).append(" ".repeat(2 * (n - stars))).append(side).append('\n');
}
return sb.toString();
}
Dry run for n = 3:
| r | r < n? | stars | gap | row |
|---|---|---|---|---|
| 0 | yes | 3 | 0 | ****** |
| 1 | yes | 2 | 2 | ** ** |
| 2 | yes | 1 | 4 | * * |
| 3 | no | 1 | 4 | * * |
| 4 | no | 2 | 2 | ** ** |
| 5 | no | 3 | 0 | ****** |
Complexity. Time O(n^2): each row is built from three repeat calls whose lengths add up to 2n. Space O(n^2) for the output plus O(n) of temporary strings per row.
A note on the symmetry: for r ≥ n the star count is r - n + 1, and for the mirror row 2n - 1 - r (which is < n) it is n - (2n - 1 - r) = r - n + 1 as well. That algebra is exactly why rows r and 2n - 1 - r are identical, and it is what the tests check for every n.
Edge cases and pitfalls
n = 0. Zero rows; both methods return the empty string.n = 1. Two identical rows**. The gap is2(1 - 1) = 0in both, so" ".repeat(0)is called, which is fine (repeatwith a negative count would throw).- Gap grows by two. Each row loses one star on the left and one on the right, so the gap grows by two characters, not one. If you write
ispaces instead of2i, the rows shrink in width and the figure leans. - Bottom half off by one. The bottom half starts with one star per side, not zero (a row with zero stars would be all spaces). Hence
i + 1stars and2(n - i - 1)spaces for 0-basedi. Check the first bottom row equals the last top row. - Even number of rows. This figure has
2nrows and no single middle row; the two centre rows are identical. Do not “fix” that by skipping one, or you get a different pattern. - Trailing newline. Every row, including the last, ends in
\n. Print the result withSystem.out.print, notprintln, to avoid a blank line. - Counting stars in tests.
row.length() - row.replace("*", "").length()is a compact way to count occurrences of a character; the tests use it to assert the star count of every row is2s.
Related problems
- Pattern 20 is this figure with the halves swapped: it starts narrow, becomes solid in the middle row, and narrows again.
- Pattern 12 uses the same
2(n - i)gap arithmetic with numbers instead of stars. - Pattern 21 is another star figure with an empty interior, this time a rectangle outline.
- Pattern 17 is a centred pattern where the symmetry runs horizontally within each row.