# Trouble understanding this simple code

``````# number of rows
rows = 5
k = 2 * rows - 2
for i in range(0, rows):
# process each column
for j in range(0, k):
# print space in pyramid
print(end=" ")
k = k - 2
for j in range(0, i + 1):
# display star
print("* ", end="")
print("")
``````

This code produces the mirror “*” triangle pattern. I can work out the first line but in the second line isn’t k iterated down to the value of 0? When i is now 1 for the second line, isn’t the second for loop for j in range (0,0)?

As you’ve observed, this prints a pyramid by printing enough spaces to
indent the first asterisk, then the appropriate number of asterisks.
Because the asterisks are separated by spaces, the indent reduces by 2
each row.

So the outer loop prints enough rows.

There are 2 inner loops. The first prints the indent, printing a single
space `k` times. The second inner loop prints the asterisks, which
prints `i+1` asterisks.

When `i=1` on the second iteration, `i+1 == 2` and thus 2 asterisks get
printed.

Some random notes:

• you can write `range(0,n)` as just `range(n)`; it will still count
from `0` through `n-1` inclusively i.e. `n` values
• if I were writing a single space, I’d probably use `print(" ",end="")`
much like the asterisk `print()` lower down, rather than printing
“nothing” and padding it with `end=" "`

Cheers,
Cameron Simpson cs@cskk.id.au

Yes, k is reduced to 0. range(0,00 is an empty sequence; no problem. Lets think about what we are doing and more directly translate to python.

Each row has `rows` chars separated (and joined) by spaces. The `rows` chars are split into `rows-i` spaces and `i` stars, where i ranges from 1 to rows. The following does this succinctly, using string multiplication and join.

``````rows = 5
for stars in range(1, rows+1):
print(' '.join(' '*(rows - stars) + '*'*stars))
``````

I often find it helpful to calculate entire lines before printing.

Thank you! So for the first line k is iterated down by two from 8 until that loop (0,k) becomes (0,0) and the asterisk loop starts and prints one asterisk, I understand that. Then on the second line it starts over with the first for loop (0,rows) now being i=1 and the second for loop (0,k) still being (0,0) no? I mean the value of k is still 0 from the previous line isn’t it? I get that it now iterates three spaces on the second line but I don’t see how k is reset since the line k=2*rows-2 is before all the loops.

Thanks!
Dave

You wrote:

So for the first line k is iterated down by two from 8 until that loop
(0,k) becomes (0,0) and the asterisk loop starts and prints one
asterisk, I understand that. Then on the second line it starts over
with the first for loop (0,rows) now being i=1 and the second for loop
(0,k) still being (0,0) no? I mean the value of k is still 0 from the
previous line isn’t it? I get that it now iterates three spaces on the
second line but I don’t see how k is reset since the line k=2*rows-2 is
before all the loops.

I think you’re misunderstanding how the loops work, the meaning of the
nesting and exactly when things get computed. I’m going to recite the
code against below then talk about it in more detail:

`````` # number of rows
rows = 5
k = 2 * rows - 2
for i in range(0, rows):
# process each column
for j in range(0, k):
# print space in pyramid
print(end=" ")
k = k - 2
for j in range(0, i + 1):
# display star
print("* ", end="")
print("")
``````

What we’ve got here is 3 loops, one outer loop and two inside it.

When you commence the outer loop:

`````` for i in range(0, rows):
``````

the expression `range(0, rows)` is computed once at this point, returing
a “range” object which counts from `0` through to `5` (excluding the
`5`, so `0` to `4` inclusive). We could fiddle with the value in `rows`
later and not affect how many times this loop runs, because the “range”

So this makes a loop setting `i` to a value of `0` for the first pass,
`1` for the next pass and so on.

Every time that loop runs, it runs everything inside it once.

The second loop:

`````` for j in range(0, k):
# print space in pyramid
print(end=" ")
``````

Again, this constructs a “range” object which counts from `0` through to
`k-1`, for the current value if `k` when the loop is started. On the
first pass of the outer loop `k=8` so this counts from `0` through to
`7` inclusive, and prints 8 spaces as a result.

Then we finish the loop, we reduce `k` by `2`. This is the only line
which changes `k`.

``````     k = k - 2
``````

`k` is now `6`. Not `0`.

I think that’s the source of your confusion. The `for j` loop does not
change k
.

Try making another Python file which this changed code:

`````` # number of rows
rows = 5
k = 2 * rows - 2
print("rows =", rows, "k =", k)
for i in range(0, rows):
print("  outer loop top: i =", i, "k =", k)
# process each column
for j in range(0, k):
print("    first inner loop: j =", j, "i =", i, "k =", k)
k = k - 2
for j in range(0, i + 1):
print("    second inner loop: j =", j, "i =", i, "k =", k)
print("DONE, i =", i, "k =", k)
``````

You should see what happens to the variables on each pass more clearly.

Cheers,
Cameron Simpson cs@cskk.id.au

Thanks so much for this. For some reason I was thinking that the value of k iterated to zero as that loop (0,k) cycled through when its j that is iterating, I was confusing j with k… Thanks again!

1 Like