Why this matters
Pattern printing is a common warm-up in first programming interviews. The interviewer draws a picture, such as a triangle made of stars, and asks you to print it. The problem looks simple, but it tests three skills that every later topic needs. You need to read a loop. You need to turn a picture into a counting rule. And you need to check your answer by hand before you run anything.
The same thinking later becomes lists of rows, grids of cells, tables of numbers and the pixels of an image. A star pattern is the smallest version of that picture, so it is a good place to build the habit.
This lesson gives one method that solves almost every star pattern: squares, rectangles, right triangles, inverted triangles and right-aligned triangles. The later lessons use the same method for numbers, letters, pyramids, hollow shapes and diamonds.
Before you write any code
A Python program is a text file. Python reads the file from top to bottom and runs each line in order. You type the program in the editor on this page and press Run. The output appears under the code. The examples in this lesson were run with Python 3.14.
A Python program needs no setup and no class or main method. A program can be a few plain lines.
Python uses indentation, the spaces at the start of a line, to show which lines belong together. Four spaces mean one level inside a loop. Every line in a loop body starts with the same four spaces, and the first line after the loop starts with fewer. A line with the wrong number of spaces is an error, as the mistakes section shows.
Some programs read a number from you. The function input() waits for you to type something in the Input box and returns what you typed as text. Text is not a number yet, so int(input()) turns the text into a whole number. If the Input box says 4, then int(input()) gives the number 4.
Two numbers on one line, separated by a space, are read with rows, cols = map(int, input().split()). The method split() cuts the text at the spaces, and map(int, ...) turns each piece into a number. The two names on the left take the two numbers in order.
Some examples do not read input. Those have the number written in the code, as n = 4, and they can run as they are.
The idea: a pattern is a grid
Every star pattern is a picture on a grid. The grid has rows, which go from top to bottom, and columns, which go from left to right. Each cell is either a star or a space. A program prints the grid by going through the cells in order: the first row from left to right, then the second row, and so on. At the end of each row the program moves to the next line.
Think of writing lines in a notebook. You decide which line you are on. Then you write the symbols of that line from left to right. When the line is full, you move down to the next line. A pair of nested loops does the same thing. The outer loop picks the line. The inner loop writes the symbols of that line. After the inner loop finishes, print() with nothing inside moves to the next line.
The method has three steps. Say them before you type any code.
- Count the rows. The number of rows sets the outer loop, and its counter is usually called
i. - For each row
i, work out how many symbols it needs. That count sets the inner loop. - After the inner loop finishes, call
print()so the next row starts on a new line.
The grid below shows a four by four square. Row 2 is marked. During the pass for row 2, the inner loop prints four stars from left to right. Then the outer loop moves to row 3, and the inner loop starts again.
row 1: * * * *
row 2: * * * * <- the inner loop prints these 4 stars
row 3: * * * *
row 4: * * * *The most useful habit in this module is to say the two loops out loud before you type them. For a square: "For each row, from 1 to n. For each star in that row, print a star. Then move to the next line." If you can say the rule in plain words, you can usually code it in a few minutes. If you cannot, draw the first three rows on paper first.
The picture gives the counts, and the counts give the loops. Each row either has the same number of stars as the row above it, or one more, or one fewer, or a number that depends on its position. Your job is to find that rule. Once you have it, the loops are a way of writing it down.
Anatomy of a for loop
A for loop repeats a block of code once for each value in a sequence. In this module the sequence almost always comes from range. Here is the loop you will see most often:
for i in range(1, 5):
print(i)The line starts with for, then the name of the counter, i, then in, then the sequence. The line ends with a colon. The lines under it, indented by four spaces, are the body. The body runs once for each value of i.
Run the example to see the values.
The output is:
1
2
3
4
[0, 1, 2, 3]range(1, 5) gives the values 1, 2, 3 and 4. The start, 1, is included. The stop, 5, is not included. The last line of the output shows range(4) by itself. With only one number, range starts at 0, and it still stops before the number, so it gives 0, 1, 2 and 3.
Pay close attention to the stop value. range(1, n) gives one value fewer than range(1, n + 1). If the last row is missing from a picture, the stop value is usually one short. The common mistakes section shows this error on screen.
The counters for rows and columns start at 1 in this module, because the rows and columns of a picture are numbered from 1. With range(1, n + 1) the values are 1 to n, which matches the picture.
Some loops need only the number of passes, not the counter. For those, the name _ (a single underscore) is a common choice. It means that the value is not used. for _ in range(4) runs four times, and the values 0, 1, 2 and 3 are ignored.
print and the end argument
In Python, print adds a line break after its text by default. The line break is what moves the cursor to the next line. The argument end changes it.
print("*", end="")prints the star and adds no line break. The next printed text appears right after it, on the same line.print()with nothing inside prints only the line break. The next printed text starts at the beginning of a new line.
Run this example. It prints two stars on one line, then starts a new line, then prints one star on the next line.
The output is:
**
*Keep the difference in mind. A pattern usually needs many prints on one line that do not end the line, and one print() at the end of that line. If you put print() inside the inner loop, every symbol gets its own line. That is almost never what a pattern wants.
A string is text in quotes. "*" is a string with one star. A space is also a string, " ", and spaces are printed the same way as stars. Spaces are what push a line to the right.
Python can also repeat a string with *. The expression "*" * 4 gives ****, and " " * 3 gives three spaces. This is a shortcut. The loops in this lesson show the method first, and the shortcut comes at the end.
Worked example 1: a square
Let us print a square of stars with four rows and four columns. The pattern needs four rows, and every row has four stars. So the outer loop runs four times, and the inner loop prints four stars on each pass.
The size is written in the code as n = 4, so this program needs no input and can run as it is.
The output is:
****
****
****
****Trace the first row. The outer loop sets i to 1. The inner loop runs four times and prints four stars. Then print() ends the line. The outer loop sets i to 2, and the inner loop prints four more stars on the next line. The same happens for rows 3 and 4.
The inner loop runs four times for each of four outer passes. That is 4 times 4, which is 16 stars. Count the stars in the output to check.
The variable n holds the size of the square. Python does not care what it is called, but n, i and j are the names most programmers expect for these jobs.
Worked example 2: a right triangle that reads n
Now let the user choose the size. A right triangle has one star in the first row, two in the second row, and so on. Row i has i stars. For n equal to 4, the last row has four stars. The triangle has a straight left edge and a slanted right edge, which is why it is called a right triangle.
This program reads n from the Input box. Save it as a file and run it with python3, then type 4 when it waits for the number.
n = int(input())
for i in range(1, n + 1):
for _ in range(i):
print("*", end="")
print()The output for an input of 4 is:
*
**
***
****The only change from the square is the inner count. The square used n stars in every row. The triangle uses i stars, which is the row number. Row 1 has one star, row 2 has two, row 3 has three and row 4 has four.
The line n = int(input()) reads the number once, at the start of the program. The loops then use n as the outer limit. The same program handles any number you type. Try 1 and 6 yourself. The one-row triangle is a single star, and the six-row triangle has a last row with six stars.
The inner loop for _ in range(i) needs no counter, because the program only needs to repeat the print i times.
Worked example 3: an inverted triangle
An inverted triangle is a right triangle turned upside down. It starts with a full row of n stars and gets one star shorter on each row. Row 1 has n stars, row 2 has n minus 1, and so on, until the last row has one star.
Use a planning table before you write the loop. Take n equal to 4, and write one line for each row.
Row i | Stars in the row |
|---|---|
| 1 | 4 |
| 2 | 3 |
| 3 | 2 |
| 4 | 1 |
The stars go down by one each time i goes up by one. A formula that fits every row is n - i + 1. Check it on the first and last rows, because errors almost always show up at the ends. For row 1 the formula gives 4 minus 1 plus 1, which is 4. For row 4 it gives 4 minus 4 plus 1, which is 1. Both match the table.
Type 4 in the Input box when you run this program saved as a file.
n = int(input())
for i in range(1, n + 1):
for _ in range(n - i + 1):
print("*", end="")
print()The output for an input of 4 is:
****
***
**
*The program has no separate counter for the stars. The inner count is the formula. If the formula is right, the picture is right. A wrong formula is the most common cause of a wrong pattern, and the table shows the error before you run anything.
Worked example 4: a right-aligned triangle
A right-aligned triangle is the right triangle pushed to the right edge, so that its stars line up against the right side. Each row needs spaces first and then stars. Row i has n - i spaces and i stars.
The planning table for n equal to 4 has one column for spaces and one for stars.
Row i | Spaces | Stars |
|---|---|---|
| 1 | 3 | 1 |
| 2 | 2 | 2 |
| 3 | 1 | 3 |
| 4 | 0 | 4 |
The spaces go down by one each row, and the stars go up by one each row. Every row adds up to n characters. If your formulas do not add up to n on every row, one of them is wrong.
The code has two inner loops, one after the other. The first prints the spaces, and the second prints the stars. Type 4 in the Input box when you run it.
n = int(input())
for i in range(1, n + 1):
for _ in range(n - i):
print(" ", end="")
for _ in range(i):
print("*", end="")
print()The output for an input of 4 is:
*
**
***
****Two things need attention. First, both inner loops use _. That is allowed here, because the first loop finishes completely before the second one starts. Second, the line break comes only after both inner loops. If you put it between them, the stars drop to a new line and the picture falls apart.
Each line ends with a star, not a space. No line has trailing spaces. Many output checkers compare text exactly, so a stray space at the end of a line can make a correct answer look wrong. When you can, arrange the loops so the last character on a line is the one that matters.
Worked example 5: a rectangle with two inputs
A rectangle has a number of rows and a number of columns. Those are two separate numbers, so the program reads two values from the Input box. The rows set the outer loop, and the columns set the inner loop. This is the same as the square, except that the two limits are different numbers.
Type 3 and 6 in the Input box, with a space between them.
rows, cols = map(int, input().split())
for i in range(1, rows + 1):
for _ in range(cols):
print("*", end="")
print()The output for 3 and 6 is:
******
******
******The line rows, cols = map(int, input().split()) reads both numbers from one line. The first number goes into rows and the second goes into cols. The order matters. If you type 6 3 instead, you get six rows of three stars. That is also a rectangle, but a different one, and it is what the program was asked to draw.
Names matter here. The condition range(1, rows + 1) reads like the rule it implements: one pass for each row.
What happens inside the loop
Python keeps each variable as a name that points to a value. When the for line runs, it sets i to the next value from range. The body runs. Then the loop asks for the next value. When the values run out, the loop stops.
Here is the right triangle with n equal to 3, traced one outer pass at a time.
Outer i | Inner loop | Output for this pass |
|---|---|---|
| 1 | runs 1 time | *, then the line break |
| 2 | runs 2 times | **, then the line break |
| 3 | runs 3 times | ***, then the line break |
Each outer pass starts the inner loop from its beginning. The inner for line sits inside the outer loop, so Python starts it again on every row. The total number of stars is 1 plus 2 plus 3, which is 6, and the output has three lines.
The counts add up in a way you can predict before you run anything. The square prints n times n stars, so with n equal to 4 it prints 16. The triangle prints 1 plus 2 plus 3 plus 4, which is 10 stars. A nested loop costs the product of its counts, so a square 100 characters wide and 100 rows high runs its print line 10,000 times. For pattern printing that is fast. The complexity topic shows how to count such costs for any loop.
Planning any pattern with a table
Before you write a loop, fill in a table with one row for each line of output. Give each column one thing you need to count. Then look for the formula in each column. A table turns a picture into arithmetic, and arithmetic is easier to check than a picture.
Your table may have only the row number and the stars. Many patterns need spaces as well. Whatever the columns are, the process is the same:
- Draw the first row, the second row and the last row of the picture on paper.
- Count the characters in each of those rows, and write the counts in the table.
- Look at how each count changes from one row to the next. Usually it goes up or down by a fixed amount. That change is the clue to the formula.
- Write the formula with
iandn, then check it on the first row and on the last row. - Write the loops, then run the program with a small n, such as 3 or 4, and compare the output with the table.
Errors almost always show up at one end. If the first row is right and the last row is wrong, the formula is off by one, and the fix is usually a + 1 or a - 1 in the range. If every row is wrong by the same amount, the mistake is usually in the way the loop starts.
A table also catches mistakes before you type any code. If the spaces column and the stars column do not add up to the row width on every line, you know a formula is wrong.
Common mistakes and their real messages
Each mistake below is one that learners make in their first week. Some stop the program from starting. Others run, but print the wrong picture. The messages quoted here are what Python printed when these programs were run for this lesson.
Mistake 1: a missing colon. Every for line ends with a colon. Without it, Python stops before it runs anything. This program has no colon after range(1, n + 1):
n = 4
for i in range(1, n + 1)
print("*")Python prints this message:
File "...", line 2
for i in range(1, n + 1)
^
SyntaxError: expected ':'The caret points to the place where the colon should be. Go to that spot and add the colon.
Mistake 2: wrong indentation. The body of a loop must be indented. This program has no indentation under the for line:
for i in range(3):
print("*")Python prints this message:
File "...", line 2
print("*")
^^^^^
IndentationError: expected an indented block after 'for' statement on line 1The fix is four spaces at the start of the print line. Every line in the same block must use the same number of spaces.
Mistake 3: a misspelled name. This program misspells print:
prnt("*")Python prints this message:
NameError: name 'prnt' is not defined. Did you mean: 'print'?The message names the word Python does not recognise, and it suggests the closest name it knows. Compare the spelling with the message and fix it.
Mistake 4: print inside the inner loop. This program runs, but the picture is wrong. The line break is inside the inner loop, so it runs after every star.
for i in range(1, 4):
for _ in range(3):
print("*", end="")
print()The output is nine lines, each with one star, instead of three lines of three stars:
*
*
*
*
*
*
*
*
*The fix is to move print() out of the inner loop, so it runs once for each row.
Mistake 5: an off-by-one range. This program stops the outer loop one value early:
n = 4
for i in range(1, n):
for _ in range(n):
print("*", end="")
print()The output has three rows, and the bottom row is missing:
****
****
****range(1, n) stops before n. The fix is range(1, n + 1), which includes n. Read the range aloud and decide whether the last value should be included.
Mistake 6: the wrong count. For an inverted triangle, range(n - i) gives one star too few on every row. The last row gets no stars at all, and the output ends with an empty line:
n = 4
for i in range(1, n + 1):
for _ in range(n - i):
print("*", end="")
print()The output is:
***
**
*
The fourth line is empty. The planning table catches this, because a row with zero stars is an obvious sign of a wrong formula. The fix is n - i + 1.
The messages point to different parts of the program. A missing colon or wrong indentation is about the text of one line. An unknown name is about spelling. A wrong picture is about the range or the formula. Learn to tell these kinds of problem apart, and you will fix most mistakes in a minute.
Debugging walkthrough: a triangle comes out upside down
Suppose you write a right triangle, but for an input of 4 the output is this:
****
***
**
*Row 1 should have one star, and it has four. That tells you which formula you used by mistake. The count n - i + 1 is the inverted triangle's formula. The right triangle needs i.
Walk through the steps as a checklist.
Step 1: compare the first row of the output with the first row you want. Row 1 has four stars, and it needs one.
Step 2: look at the inner count. If it reads range(n - i + 1), you wrote the inverted formula. Change it to range(i).
Step 3: run the program again. Row 1 should now have one star.
Step 4: check the last row. For an input of 4 it should have four stars. With range(i) and i equal to 4, the count is 4, so the last row has four stars. Both ends are now correct, so the picture is correct.
A second technique is to add a temporary line that prints the counter. For example, print("[", i, "]", end="") placed inside the inner loop prints the row number on every pass. Remove that line when you have finished, because it spoils the picture.
A third technique is to shrink the input. Run the program with an input of 2. Two rows are easy to check by eye, and most bugs appear at the smallest size that shows them.
Variations and edge cases
A pattern program should work for every size a user might type. Think about the edge cases before you finish, and test them.
For n equal to 1, every pattern prints a single star. The square, the right triangle and the inverted triangle each print one star. A formula that is off by one often gives 0 stars or 2 stars at this size.
For n equal to 0, the right triangle program prints nothing, because range(1, 1) has no values and the outer loop never runs. The program does not crash.
For a negative number, such as -3, the result is the same. range(1, -2) has no values, so nothing is printed. If you want an error message for bad input, check the number first with an if statement, which the conditionals module teaches.
There are two more variations worth knowing. The first is to change the symbol. Replace "*" with "#" or "@", and the picture keeps its shape. The second is to swap the two numbers in a rectangle. A rectangle with 3 rows and 6 columns is wide and short. Swapping the numbers gives a tall, narrow rectangle. If a test expects one shape and your program prints the other, the bug is almost always the order in which you read the two numbers.
Interview questions and real uses
Interviewers ask pattern questions for two reasons. They want to see whether you can write nested loops without help, and they want to hear how you think. A good answer names the loops first, then the formulas, then the edge cases.
Imagine the question: print a right-aligned pyramid of n rows. A strong answer sounds like this. "There are n rows, so the outer loop runs n times. Row i has n minus i spaces and i stars, so there are two inner loops, one for the spaces and one for the stars. I will check n equal to 1 by hand, and n equal to 3 on paper, before I run the code." The answer also says what it will check, which shows that you know how to test your own work.
Another common question gives a program and asks for its output. You answer by tracing the loops, not by guessing. Count the passes of the outer loop. For each pass, count the passes of the inner loop. Write the output one line at a time, and only then say what it prints.
The same skills appear far outside pattern printing. A grid of cells in a spreadsheet, the pixels of a picture and the seats in a cinema are all rows and columns. A nested loop is how a program visits every cell. When you later use lists of lists, the outer loop will be the row and the inner loop will be the column. The star pattern was the first grid you printed.
A shorter way to print each row
Python can build each row as one string and print it. The * operator repeats a string, as shown earlier. This program prints the right-aligned triangle for n equal to 4 in fewer lines.
The output is:
*
**
***
****Use the loop version while you learn the method. Once the planning table is clear, the one-line version is shorter, and it is common in real Python code.
Practice
Try each exercise before you open its answer. The first two use the Input box. For the rest, write the program and trace a small n by hand before you run it.
Exercise 1. Print a rectangle with 3 rows and 6 columns of stars. Then change the program so it reads the two numbers from the Input box. The input 2 5 should give two rows of five stars.
Show the answer
Use two loops. The outer loop runs rows times and the inner loop runs cols times. Read both numbers with rows, cols = map(int, input().split()). For the input 3 6 the output is three lines of six stars.
Exercise 2. Print an upside-down left-aligned triangle with 5 rows. The first row has 5 stars, then 4, 3, 2 and 1. Fill in the planning table before you write any code.
Show the answer
Row i has n - i + 1 stars. For n equal to 5 the table reads 5, 4, 3, 2, 1. The code is the inverted triangle from worked example 3, with the input 5. The output is five stars on the first line, four on the second, and so on down to one star.
Exercise 3. Print the right-aligned inverted triangle with n equal to 4. Hint: row i has i - 1 spaces and n - i + 1 stars. Check the first and last rows.
Show the answer
The output is:
****
***
**
*Use one inner loop for the spaces, for _ in range(i - 1):, and a second inner loop for the stars, for _ in range(n - i + 1):. Row 1 has no spaces and four stars. Row 4 has three spaces and one star.
Exercise 4. Predict the output of this program, then run it to check.
Show the answer
The output is one star, then two stars, then three stars, each on its own line. Row i has i stars because range(1, i + 1) gives the values 1 to i. If you predicted three rows of three stars, you used range(1, 4) for the inner loop instead of range(1, i + 1).
Exercise 5. Write a program that prints an n by n square with a border of @ and spaces inside. For n equal to 4 the output has four lines. Use if to choose the symbol.
Show the answer
The border is the first row, the last row, the first column and the last column. Each cell checks whether it is on the border. An if line runs the indented lines under it only when its test is true. == checks that two values are equal, and or makes the test true when either side is true.
The output is:
@@@@
@ @
@ @
@@@@Exercise 6. Print the right triangle for n equal to 6, but put the row number in front of each row's stars, with a space between them. Row 1 is 1 *, row 2 is 2 **, and so on. Write the expected output on paper first.
Show the answer
Print the row number with print(i, end=" ") before the inner loop. The argument end=" " replaces the line break with a space, so the stars start right after the number. Row 3 is 3 ***.
Exercise 7. Find the bug. A program should print a square of n stars with n equal to 3. Instead it prints three lines: the first line has three stars, the second has two, and the third has one. What is wrong?
Show the answer
The inner count depends on i, for example range(n - i + 1), but a square needs every row to have n stars. Change the inner count to range(n). The rows of a square never shrink.
Exercise 8. Read the input as rows and then columns. Predict what the program prints for the input 0 5, and then for the input 5 0. Explain each answer.
rows, cols = map(int, input().split())
for i in range(1, rows + 1):
for _ in range(cols):
print("*", end="")
print()Show the answer
The input 0 5 prints nothing. range(1, 1) has no values, so the outer loop never runs. The input 5 0 prints five empty lines. The outer loop runs five times, the inner loop never prints a star, and print() still ends each row, so five blank lines appear.
Exercise 9. Print a diagonal of n rows with n equal to 4. Row i has i - 1 spaces and then one star. Write the table of spaces and stars first.
Show the answer
The output is:
*
*
*
*The spaces loop runs i - 1 times, and then print("*") prints the star and the line break in one call.
Exercise 10. Print a rectangle with 5 rows and 7 columns, with the middle empty. Read the two numbers from the Input box. Do not use if yet. Hint: the first row and the last row are full, and each middle row has a star at each side.
Show the answer
Print the full rows with "*" * cols, and print each middle row as a star, then spaces, then a star. Put the middle rows in a loop that runs rows - 2 times.
rows, cols = map(int, input().split())
print("*" * cols)
for _ in range(rows - 2):
print("*" + " " * (cols - 2) + "*")
print("*" * cols)For the input 5 7 the output is:
*******
* *
* *
* *
*******Summary
Three details from this lesson carry into the next one. The stop value of range is not included, so use n + 1 when the value n must be printed. The end argument of print decides whether a line ends. Each input() returns text, and int turns it into a number.
If you know Java, the nested loops are the same. The changes are that range replaces the three-part for line, print(..., end="") replaces the print call with no line break, and indentation replaces the curly brackets.