Pattern Programming with Nested Loops

Printing shapes with loops teaches nested iteration better than any explanation. Every pattern comes from the same three questions.

Why patterns are worth doing

Pattern problems have no practical use in themselves. They are worth an hour of your time because they force you to reason precisely about nested loops, about the relationship between the outer and inner counters, and about where the line break belongs. Interviewers use them for exactly that reason.

The three questions

Every pattern is solved by answering these in order:

  1. How many lines? That is the outer loop.
  2. What appears on line i? That is the inner loop or loops.
  3. How does the count on each line relate to i? That is the formula.

The essential tool: print(end="")

print("*")              # prints a star and moves to the next line
print("*", end="")      # prints a star and stays on the same line
print()                 # prints nothing and moves to the next line

Everything below relies on those three forms.

Square

n = 4
for i in range(n):
    for j in range(n):
        print("*", end=" ")
    print()
* * * *
* * * *
* * * *
* * * *

Right angled triangle

n = 5
for i in range(1, n + 1):
    for j in range(i):          # line i has i stars
        print("*", end=" ")
    print()
*
* *
* * *
* * * *
* * * * *

Inverted triangle

n = 5
for i in range(n, 0, -1):
    print("* " * i)
* * * * *
* * * *
* * *
* *
*

"* " * i replaces the inner loop entirely. Repetition is often clearer than a loop for a single repeated character.

Pyramid

A pyramid needs two inner parts: leading spaces, then stars. On line i of n, there are n - i spaces and 2i - 1 stars.

n = 5
for i in range(1, n + 1):
    print(" " * (n - i) + "* " * i)
    *
   * *
  * * *
 * * * *
* * * * *

The same thing with explicit loops

n = 5
for i in range(1, n + 1):
    for space in range(n - i):
        print(" ", end="")
    for star in range(2 * i - 1):
        print("*", end="")
    print()

Diamond

n = 4

for i in range(1, n + 1):                 # upper half
    print(" " * (n - i) + "*" * (2 * i - 1))

for i in range(n - 1, 0, -1):             # lower half
    print(" " * (n - i) + "*" * (2 * i - 1))
   *
  ***
 *****
*******
 *****
  ***
   *

Number patterns

n = 5

# Same number on each line
for i in range(1, n + 1):
    print((str(i) + " ") * i)

print()

# Counting from 1 on every line
for i in range(1, n + 1):
    for j in range(1, i + 1):
        print(j, end=" ")
    print()
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5

1
1 2
1 2 3
1 2 3 4
1 2 3 4 5

Floyd's triangle

n = 5
value = 1
for i in range(1, n + 1):
    for j in range(i):
        print(value, end=" ")
        value += 1
    print()
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15

Note that the counter lives outside both loops. That is what makes the numbering continuous across lines.

Pascal's triangle

n = 6
row = [1]

for i in range(n):
    print(" " * (n - i) + " ".join(str(v) for v in row))
    row = [1] + [row[j] + row[j + 1] for j in range(len(row) - 1)] + [1]
      1
     1 1
    1 2 1
   1 3 3 1
  1 4 6 4 1
 1 5 10 10 5 1

Character patterns

n = 5

for i in range(n):
    for j in range(i + 1):
        print(chr(65 + j), end=" ")     # 65 is the code point of A
    print()

print()

for i in range(n):
    print((chr(65 + i) + " ") * (i + 1))
A
A B
A B C
A B C D
A B C D E

A
B B
C C C
D D D D
E E E E E

Hollow square

n = 5
for i in range(n):
    for j in range(n):
        if i in (0, n - 1) or j in (0, n - 1):
            print("*", end=" ")
        else:
            print(" ", end=" ")
    print()
* * * * *
*       *
*       *
*       *
* * * * *

A hollow shape is the solid shape plus one condition deciding whether each position is on the border.

Common mistakes

  • Forgetting the bare print() at the end of the outer loop, so everything lands on one line.
  • Putting the line break inside the inner loop, so every character lands on its own line.
  • Off by one errors in range. Write down the count for line 1 and line n and check both.
  • Using print(" " * n) and then wondering why trailing spaces are invisible.
  • Declaring a running counter inside the outer loop when it should persist across lines.

Best practices

  • Work out the formula for the first and last line on paper before writing any code.
  • Use string repetition instead of an inner loop when the character does not change.
  • Test with n = 1 and n = 2; that is where off by one errors show themselves.
  • Keep n in a variable so a pattern can be resized in one place.

Practice

  1. Print a left aligned inverted triangle, then centre it.
  2. Print a hollow pyramid, showing the border stars only.
  3. Print a butterfly pattern: two triangles facing each other with spaces between them.
  4. Print a number pyramid where each line reads up and back down, for example 1 2 3 2 1.
  5. Print a chessboard of * and spaces for a given size.

Conclusion

Patterns reduce to counting: how many lines, what is on each line, and how that count relates to the line number. Answer those three questions before writing a loop, and the code follows in a couple of minutes.

Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All Python notes →
Python

The for Loop and range()

A Python for loop walks over the items of a collection directly. range() supplies numbers when you genuinely need a counter, which is less often than...

Read more
Python

The while Loop

while repeats for as long as a condition holds. Use it when the number of repetitions is unknown, and make sure something inside the loop can make the...

Read more

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.