Why this matters
Every pattern in the previous lesson filled its shape. A solid square, a solid triangle and a solid pyramid print a star wherever the loops reach. A hollow pattern is different. It prints stars only on the outline and spaces inside. Hollow shapes are a common interview question, because they make you decide something for every cell instead of printing the same symbol everywhere.
The decision is the central idea of this lesson. In the previous lesson the loops decided how many symbols to print. Here the loops visit every cell, and a condition decides what goes into that cell. A condition is a question that the program answers with True or False, and an if statement acts on the answer. Once you can write a border condition, you can draw almost any outline.
The lesson also shows a habit that real programs need. Test a rule on the first and last cases, not only on the middle. The corners, the first row and the last row are where a rule most often fails, so check those first.
Every program below was run with Python 3.14, and the output shown is what it printed. To try another size, change the value of n on the first line of a program.
The idea: a cell is a star only on the border
Take a hollow square with five rows and five columns. Number the rows i from 1 at the top to 5 at the bottom, and the columns j from 1 at the left to 5 at the right. A cell is on the border when it is in the first row, or the last row, or the first column, or the last column. Every other cell is inside the square and should print a space.
In words, the test is: is i equal to 1, or is i equal to n, or is j equal to 1, or is j equal to n? If any of those is true, print a star. If none is true, print a space. In Python the word "or" is written or, and the test for equality is ==. The whole test reads i == 1 or i == n or j == 1 or j == n.
The border of a five by five square has 16 cells, which is the outer ring. The inside has 9 cells, a three by three block. Those counts add up to 25, the total number of cells. That count is a useful check on any hollow pattern you draw.
An if statement runs one block when its condition is True. An else block runs when the condition is False. Exactly one of the two blocks runs for each cell, and that is the decision the hollow pattern needs.
if i == 1 or i == n or j == 1 or j == n:
print("*", end="")
else:
print(" ", end="")The line ends with a colon, and the blocks under it are indented. Python uses the indentation to see which lines belong to the if. Both blocks must be indented by the same amount under their keyword.
Boolean conditions: and, or and not
A condition has a true or false answer. Python calls that type bool, and the two values are written True and False. A comparison such as i == 1 produces a bool. You can combine comparisons with three words, and each one works like its English meaning.
ormeans "either side, or both". The whole condition isTrueif at least one part isTrue.i == 1 or j == 1isTruewhen the row is 1, or the column is 1, or both.andmeans "both sides". The whole condition isTrueonly if every part isTrue.i == 1 and j == 1isTrueonly at the top left corner.notflips a value.not i == 1isTruefor every row except the first.
For the border you need or, because a cell is on the border if it meets any one of the four edge tests. This is the most common place for a mistake. A learner writes and because "it has to be on the top and the left" sounds like the right idea, and the result is a picture with only corners printed. Read the condition aloud and check the word. A cell on the top edge alone is a border cell, so the test is or.
It helps to give the condition a name. The if statement then reads like a sentence.
The output is:
***
* *
***Both forms do the same job. The named version is easier to read and to test. Choose a name that says what the test means. border is better than x, because the reader knows what the test is for without reading the whole condition.
Python evaluates or and and from left to right, and it stops as soon as the answer is known. This is called short-circuit evaluation. The next program shows which checks run.
The output is:
checking a
checking b
inside
checking c
checking dThe first or checks a, which is False, so it must check b. The second and checks c, which is True, so it must check d. A test that is decided early skips the rest. The border tests in this lesson change nothing, so the order does not change the picture. The order matters when a test reads from a list, such as i < len(a) and a[i] == x, because the first part must stop the second part from reading past the end of the list.
Worked example 1: a hollow square
The program below prints a hollow square. The outer loop runs over the rows, and the inner loop runs over the columns of each row. The inner loop does not decide the symbol by counting. It asks the border question for each cell and prints the answer.
The output is:
*****
* *
* *
* *
*****Trace the second row. The outer loop sets i to 2. The inner loop runs for j from 1 to 5. For j equal to 1 the test j == 1 is True, so the cell is a star. For j equal to 2, 3 and 4 all four tests are False, because i is 2, which is neither 1 nor 5, and j is neither 1 nor 5. Those cells print spaces. For j equal to 5 the test j == n is True, so the last cell is a star. The row is a star, three spaces and a star.
Look at the first and last rows as well. In row 1 the test i == 1 is True for every column, so every cell is a star. Row 5 works the same way, because i == n is True there. The top and bottom are solid, and the sides are the only parts that change.
The program works for any size, because it never counts stars. It asks the question for each cell. Change n to 3 and you get a hollow square with a single space in the middle. Change it to 1 and you get one star, because that cell is on all four edges at once. The condition is True in every case, so one star is printed, and the picture is right.
Worked example 2: a hollow rectangle
A rectangle has two sizes, rows and columns. The border test works the same way, but it uses two limits. The top and bottom rows are at i equal to 1 and i equal to rows. The left and right columns are at j equal to 1 and j equal to cols.
The output is:
*******
* *
*******Compare this with the square. The only change is the names of the limits. The square had one size, n, for both directions. The rectangle has rows and cols, and the test for the bottom edge is i == rows, not i == cols. Mixing those two names is a common bug, and it is covered in the mistakes section.
The middle row has five spaces. The two edges take two of the seven columns, so five columns are inside the rectangle.
Worked example 3: a hollow right triangle
A hollow right triangle has a straight left edge, a slanted right edge and a solid base. A cell is on the border in three cases. It is on the left edge when j is 1. It is on the slanted edge when j equals i, which is the last cell of its row. It is on the base when i equals n.
This shape needs different loops from the square. Row i has i cells, so the inner loop runs from 1 to i, not from 1 to n. The planning table shows the cells before any code is written.
Row i | Cells in the row | Star positions |
|---|---|---|
| 1 | 1 | j = 1 |
| 2 | 2 | j = 1, 2 |
| 3 | 3 | j = 1, 3 |
| 4 | 4 | j = 1, 4 |
| 5 | 5 | all of j from 1 to 5 |
The left edge is always j equal to 1. The slanted edge is the last cell of each row, so it moves one place to the right on each row. The base row is the last row, where every cell is on the border. The base row is solid, while the other rows have spaces inside.
The output is:
*
**
* *
* *
*****Check the output against the table. Row 3 has cells j equal to 1, 2 and 3. The test is True for j equal to 1 and for j equal to 3, which is i. So the row is a star, a space and a star. Row 4 has cells 1 to 4, and the test is True for 1 and for 4, so the row is a star, two spaces and a star. Row 5 is the base, and i == n is True for every cell, so the row is five stars.
Row 2 has two cells, and both are on the border. The left edge is j equal to 1, and the slanted edge is j equal to 2. No space is printed, so the row is **. A row with only two cells is always solid, because every cell is on an edge. Many learners expect a space in row 2, and the table shows why there is none.
Worked example 4: a hollow pyramid
The hollow pyramid combines two ideas. It is centred, so each row starts with spaces, as in the previous lesson. It also has a border, so each row needs a test for its first cell and its last cell, plus a test for the base row. Row i has 2 * i - 1 cells. The cell at position k is on the border when k is 1, or when k is 2 * i - 1, or when the row is the base, i equal to n.
The inner loop uses k for the position inside the row, and j is not used. Choosing a different name for the position stops a reader from confusing it with a loop counter for the columns of a grid.
The output is:
*
* *
* *
*******Trace row 2 with n equal to 4. The outer loop sets i to 2. The spaces loop runs n - i, which is 2 times, so it prints two spaces. The cell loop runs for k from 1 to 2 * 2 - 1, which is 3. For k equal to 1 the first test is True, so a star is printed. For k equal to 2 all the tests are False, so a space is printed. For k equal to 3 the test k == 2 * i - 1 is True, so a star is printed. The row is two spaces, a star, a space and a star.
The base row is row 4. The outer loop sets i to 4, which equals n. The test i == n is True for every cell, so the row is seven stars with no spaces.
Row 1 has a single cell. Its first cell is also its last cell, because k equal to 1 and k equal to 2 * 1 - 1, which is 1, are the same cell. The test is True, so the single cell is a star. This is the one row where the two edge tests point at the same cell, and it is the reason the top looks right without any special case.
Worked example 5: a hollow inverted triangle
A hollow inverted triangle is the upside-down version of the hollow right triangle. It has a solid top row, a left edge that goes straight down, and a slanted right edge that moves one place to the left on each row. Row i has n - i + 1 cells. A cell is on the border when it is in the first row, i equal to 1, or in the first column, j equal to 1, or in the last cell of its row, j equal to n - i + 1.
Build the table before you write the test. For n equal to 4:
Row i | Cells in the row | Border cells |
|---|---|---|
| 1 | 4 | all four |
| 2 | 3 | j = 1 and j = 3 |
| 3 | 2 | j = 1 and j = 2 |
| 4 | 1 | j = 1 |
Row 1 is solid because every cell is in the top row. Row 2 has a space in the middle, because the middle cell is neither on the left nor on the right. Row 3 is solid, not because it is the top row, but because it has only two cells and both are on an edge. Row 4 is a single star, for the same reason.
A range ends before its stop value. To include the cell n - i + 1, the stop must be n - i + 2. This is the most common off-by-one error in this lesson, so the loop below writes the stop value as n - i + 2.
The output is:
****
* *
**
*The condition joins three tests with or. A cell needs only one of them to be a star. It is in the top row, or in the left column, or at the slanted end of its row. The end of each row moves with i, so the test for it uses n - i + 1. A test that uses a fixed column, such as j == n, would put the slanted edge in the wrong place for every row below the first.
Compare this program with the hollow right triangle in worked example 3. Both tests check one edge at a time, but the edges are in different places. The right triangle's slanted edge is at j equal to i, and the inverted triangle's is at j equal to n - i + 1. Writing down where each edge is comes before writing any loop.
What happens inside the program
Each cell in a hollow pattern costs the same work as a solid cell. The program still visits every cell and runs the same loops. The only extra work is the condition, which is a few comparisons. A hollow square of 100 by 100 cells checks 10,000 conditions, which takes very little time on any computer. The extra cost is in the thinking, because you must know what every cell means before you write the test.
The condition for each cell depends only on its row number and column number. It does not depend on what was printed before. The program needs no memory of earlier cells, because each cell answers its own question. That makes the program easy to test. If the condition is right for every pair of row and column, the picture is right.
Comparing the border tests
Every hollow shape in this lesson uses the same method. You write down where the edges are, and then you join the edge tests with or. The shapes differ only in their edges, so the tests are easier to compare side by side.
| Shape | Edge tests | Why these edges |
|---|---|---|
Square, n by n | i == 1, i == n, j == 1, j == n | Four straight sides |
Rectangle, rows by cols | i == 1, i == rows, j == 1, j == cols | The same four sides, with two different limits |
| Right triangle | j == 1, j == i, i == n | A left side, a slanted side and a solid base |
| Pyramid | k == 1, k == 2 * i - 1, i == n | The first cell, the last cell and a solid base |
| Inverted triangle | i == 1, j == 1, j == n - i + 1 | A solid top, a left side and a slanted side |
The square needs four tests because it has four sides. The right triangle needs three, because its top is not a separate edge. The top row has one cell, and that cell is already on the left side. The pyramid uses the position k within the row, because its rows are centred and its edges do not sit in fixed columns. The inverted triangle has a solid top, because its first row is the widest, and its slanted end moves with i.
When you meet a new shape, write its edges in a table like this one before you write any code. If you can name the edges, you can write the test. If you cannot name them, draw the first three rows on paper, mark the edge cells, and then write the test.
Common mistakes and their real messages
The file names and paths in the tracebacks below depend on where you save your file, so they will differ on your machine. The last line of each message is what Python printed.
Mistake 1: and instead of or. This is the most common hollow-pattern bug. A learner writes i == 1 and j == 1 or i == n and j == n, or i == 1 and i == n, and the output shows only corners. For n equal to 3, the output looks like this:
*
*The fix is to read the condition aloud, and to check that each edge is a separate alternative joined by or. A cell on the top edge is a star even when it is not in the first column, so the top test cannot be joined to the left test with and.
Mistake 2: testing the wrong limit. In a rectangle, the bottom edge test must use rows, and the right edge test must use cols. Writing i == cols for the bottom makes the bottom edge appear at the wrong row. For rows equal to 3 and cols equal to 7, the bottom edge is missing:
*******
* *
* *Read each limit name, and match it to its direction.
Mistake 3: forgetting the base of a triangle. A hollow right triangle needs i == n in its condition, so the base is solid. Without that test, the bottom row shows only its two edges, and the triangle looks open at the bottom. The table makes the base visible, because the last row has every cell on the border.
Mistake 4: a missing else. If the program has an if statement but no else, the inside cells print nothing. The row becomes shorter, and the picture is not lined up. For n equal to 3 the output is:
***
**
***The middle row has only two characters, because the inside cell printed nothing. The fix is an else block that prints a space, or a print(" ", end="") in every case that is not a star. Count the characters in a row to check that every row has the same width.
Mistake 5: a position test that uses the wrong count. In the hollow pyramid, the last cell of row i is at k equal to 2 * i - 1. Writing k == i or k == n puts the right edge in the wrong place. Check the last cell of row 2, which must be at position 3, not 2 and not 4.
Mistake 6: the stop value of a range is one too small. In the inverted triangle, range(1, n - i + 1) stops one cell too early, so the last cell of each row is never printed. The correct stop value is n - i + 2. This is the same rule as in the previous lesson: a range stop is never included.
Mistake 7: a line break is missing. Every row of a hollow pattern needs its line break after the cell loop. If print() is inside the inner loop, every cell moves to a new line. If it is missing, the whole picture prints on one line. The fix is to put print() one level outside the inner loop.
Mistake 8: = used where == is needed. In Python a single = assigns a value, and it is not a comparison. An if line with = is a syntax error, and Python prints a suggestion:
File "pattern.py", line 3
if i = 1 or i == n:
^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?The fix is == for the comparison. Python stops before it runs any part of the file, so this mistake never produces a partial picture.
Each mistake leaves a sign in the output. A corners-only picture points to and. A bottom edge in the wrong place points to the wrong limit. A missing base points to the base test. A short row points to the missing else. Learn these signs, and you can find the bug before you read the code.
Debugging walkthrough: a square with only corners
Suppose you write a hollow square with this condition, and run it for n equal to 3:
if i == 1 and j == 1 or i == n and j == n:The picture has two stars, one at each of two opposite corners, and every other cell is blank. You expected a full outline, so the condition is wrong.
Step 1: name the cells that should be stars for n equal to 3. Every cell in the first row, the last row, the first column and the last column. That is eight cells, and the centre is the only blank one.
Step 2: read the condition in words. The first part says "row 1 and column 1", which is one corner. The second part says "row n and column n", which is the opposite corner. The whole condition is True only at those two corners. The cell in row 1, column 2 is not a corner, so the first part is False for it.
Step 3: compare the words with the rule. A border cell must meet one edge test, not two. So the operators must be or between the four tests, not and inside each pair. The rule becomes i == 1 or i == n or j == 1 or j == n.
Step 4: run the program again with n equal to 3. The picture is now a square outline with one blank cell in the middle. The border of a three by three square has eight cells, which matches the picture.
A second technique helps here. Print the test result for each cell, using 1 for a border cell and 0 for an inside cell. The grid of numbers shows the rule at a glance, and it is easy to check against the table. Remove the test output when the rule is right.
Variations and edge cases
For n equal to 1 the hollow square prints one star. The cell is on every edge at once, so the test is True, and the picture is correct. A program that prints a space here usually uses and where it needs or, because and would require the cell to meet all four tests at once.
For n equal to 2 the hollow square is a solid two by two block. Every cell is on the border, because a two by two square has no inside. That is correct, and it is a good test case, because it catches off-by-one errors in the inside cells.
For a rectangle with one row, the picture is one solid line. A rectangle with one column is a vertical line of stars, because every cell is on the left and right edge at once.
A hollow pattern can use any symbol for the border and any symbol for the inside. Replace the star with # for the border and . for the inside, and the rule does not change. This is useful when a space is hard to see, because a dot makes the inside visible.
The output is:
####
#..#
#..#
####The hollow triangle and the hollow pyramid are not the same shape, even though they look similar. The triangle has a straight left edge and a slanted right edge. The pyramid has two slanted edges, and the first and last cell of each row are both on the border. The condition is different for each, so draw the shape and mark the border before you write the test.
Interview questions and real uses
Interviewers like hollow patterns because the question tests reasoning, not memory. The question is simple: print a hollow square, or a hollow triangle, for a given n. A strong answer does four things. It states the border rule in words, writes the rule as a condition, checks the rule on the corners and the base, and gives the cell count that shows the border is right. Most candidates forget the corner check, so it is the part interviewers listen for.
A common follow-up asks for the number of stars in a hollow square without printing it. A hollow square of size n has a border of 4 * n - 4 cells. The four edges each have n cells, and the four corners are counted twice, so the formula subtracts 4. For n equal to 4 the count is 12. The program below checks that count by building the border list and counting it. The square brackets hold a list comprehension, which is a loop that builds a list in one line. Its if keeps only the border cells.
The output is:
border cells: 12
formula 4 * n - 4 = 12Hollow shapes appear in real software too. A selection box around a word on a screen is an outline. A border drawn around a table is an outline. A wireframe in a design tool is an outline. In each case the program decides for each pixel or character whether it lies on the edge, and the rule is a condition like the ones in this lesson.
Practice
Try each exercise before you open its answer. Write the program, and check it on paper with a small n before you run it.
-
Print a hollow square with
nequal to 3. Predict the picture first, then check it with the program.Show the answer
The output is
***, then* *, then***. The border test isi == 1 or i == n or j == 1 or j == n, withnequal to 3. The middle cell is the only space. -
Print a hollow rectangle with 4 rows and 2 columns. Predict whether any cell is a space before you run the program.
Show the answer
No cell is a space. With only two columns, both columns are edges, so every cell is on the border. The output is
**four times, one pair on each line. Remember this case when a shape is very narrow. -
Print a hollow right triangle with
nequal to 4. Write the table of star positions first.Show the answer
The output is
*, then**, then* *, then****. Row 3 has stars atjequal to 1 and 3. The base row is solid, becausei == nisTruefor every cell. -
Print a hollow inverted triangle with
nequal to 4. Rowihasn - i + 1cells. The border is the first row, the first cell of each row, and the last cell of each row. Remember that the stop value of the innerrangemust ben - i + 2.Show the answer
The output is
****, then* *, then**, then*. The test isi == 1 or j == 1 or j == n - i + 1. Row 1 is solid becausei == 1isTruefor every cell. Row 3 has two cells, and both are on the border, so it is solid. -
Predict the output of the hollow pyramid with
nequal to 3, then check it with the program from worked example 4.Show the answer
The output is
*, then* *, then*****. The top row has one cell, which is both the first and the last. The base row is solid becausei == n. -
Count the stars in the hollow pyramid with
nequal to 5, without printing the picture. Explain how you counted.Show the answer
The total is 16. Row 1 has one star, because its only cell is both edges. Rows 2 to 4 each have two stars, at the first and last cell, which is 6 in total. The base row has nine stars, because every cell is on the border. Adding them gives 1 plus 6 plus 9, which is 16.
-
Rewrite the hollow square with a named variable called
border. Then write theifstatement so it reads like a sentence.Show the answer
Write
border = i == 1 or i == n or j == 1 or j == n, thenif border:with a star in the block andelse:with a space. The output is unchanged. The named version is easier to test, because you can print the value ofborderfor a few cells to check it. -
A program prints a hollow square, but only the four corners are stars. The condition is
i == 1 and j == 1 or i == n and j == n, and the top edge is blank. Explain the bug and write the fixed condition.Show the answer
The program uses
andinside each pair, so it asks for two edges at once, and only the corners meet both tests. An edge cell meets one test, not two. The fix isi == 1 or i == n or j == 1 or j == n, withorbetween every test. Read the condition aloud: a cell on any edge is on the border. -
Print a hollow square with
nequal to 4, using#for the border and.for the inside. Predict how many dots appear.Show the answer
The inside of a four by four square is a two by two block, so there are four dots. The output is
####, then#..#, then#..#, then####. Only the symbols in theprintcalls change. The condition is the same as in the star version. -
Print a hollow rectangle with 1 row and 4 columns. Predict the output before you run it, then explain why the rule still works without a special case for one row.
Show the answer
The output is
****. With one row, the testi == 1isTruefor every cell, because the row is both the top and the bottom. The condition isTruefor every cell in that row, so no special case is needed.
What you now know
- A hollow pattern decides, for each cell, whether it lies on the border. Only border cells print a star.
- A border test is a list of edge checks joined with
or. Joining them withandproduces a picture with only corners. - An
ifstatement with anelseblock chooses between a star and a space for every cell. - Use the row limit for the bottom edge and the column limit for the right edge of a rectangle, and check each name.
- A hollow triangle needs the base test
i == nso its bottom row is solid. A hollow pyramid needs the first and last cell of each row, which are atkequal to 1 andkequal to2 * i - 1. - Check a hollow pattern by counting its border cells, and by testing the narrowest sizes,
nequal to 1 andnequal to 2.