Here is what I think this exercise is trying to teach you.
Let's take your triangle code (there is nothing fundamentally wrong with it):
size = int(input())
for i in range(size):
for j in range(i, size):
print(" ", end = "")
for j in range(i):
print("*", end = "")
for j in range(i + 1):
print("*", end = "")
print()
and turn it into a function that returns a list of rows/lines:
def triangle(size):
rows = []
for i in range(size):
row = []
for j in range(i + 1, size):
row.append(" ")
for j in range(2 * i + 1): # i + (i+1) = 2*i+1.
row.append("*")
for j in range(i + 1, size): # Let's add spaces at the end, too.
row.append(" ") # It'll make sense in a moment!
rows.append("".join(row))
return rows
for row in triangle(5):
print(row)
# *
# ***
# *****
# *******
# *********
Now we can tweak it a little bit to work with any rectangular list-of-strings "building block" instead of *
:
def triangle(size, block):
rows = []
for i in range(size):
strip = [[] for _ in block]
for j in range(i + 1, size):
for s, b in zip(strip, block):
s.append(" " * len(b)) # Space as wide as the building block
for j in range(2 * i + 1):
for s, b in zip(strip, block):
s.append(b)
for j in range(i + 1, size):
for s, b in zip(strip, block):
s.append(" " * len(b))
for s in strip:
rows.append("".join(s))
return rows
# Make a triangle out of ["abc",
# "def"]:
for row in triangle(3, ["abc", "def"]):
print(row)
# abc
# def
# abcabcabc
# defdefdef
# abcabcabcabcabc
# defdefdefdefdef
This is somewhat tricky code! Try adding some print()
statements to this code to see how it works. zip()
loops over two lists in parallel. Actually, you should try rewriting this function yourself from scratch.
The payoff is very satisfying:
fractal = triangle(4, triangle(4, ["*"]))
for row in fractal:
print(row)
# *
# ***
# *****
# *******
# * * *
# *** *** ***
# ***** ***** *****
# *********************
# * * * * *
# *** *** *** *** ***
# ***** ***** ***** ***** *****
# ***********************************
# * * * * * * *
# *** *** *** *** *** *** ***
# ***** ***** ***** ***** ***** ***** *****
# *************************************************
You can of course also now create a "triangle of triangles of triangles":
for row in triangle(2, triangle(2, triangle(2, ["()"]))):
print(row)
# ()
# ()()()
# () () ()
# ()()()()()()()()()
# () () ()
# ()()() ()()() ()()()
# () () () () () () () () ()
# ()()()()()()()()()()()()()()()()()()()()()()()()()()()
The lesson here is that of generalizing a problem: on the face of it, it's hard to make a triangle of triangles (of triangles). But it's relatively easy to make a triangle out of whatever.
If we write some code that can make triangles out of anything (like our abc def
example), we can use that code to make a triangle out of triangles.
Unlike the other answers, we don't need separate logic for the two layers of "triangle" at play here.