Reputation: 27
I am trying to write code that will display a shape with an odd width. Once the shape is completed it is placed inside an outer shape. The user will be able to input the characters used for the shape and the number of rows. I am hoping to produce a shape and, with a for loop, produce an outer shape.
***** .
*** ...
* .....
.*****.
...***...
.....*.....
this is my current code. I only know how to create a shape.
char = (input("Enter first charactrer"))
rows = int(input("enter the number of rows"))
for m in range(rows, 0, -1):
for n in range(0, rows-m):
print(end=" ")
for n in range(0,m):
print(char,end=" ")
print()
Upvotes: 1
Views: 102
Reputation: 20414
A useful feature in python is the way you can multiply a char
by an int
to get a string
of that repeated char
.
For example, if you do:
'c' * 10
you get:
'cccccccccc'
The reason this will be useful in your case is that you can use it to print the spaces
and chars
. This will be neater than for-loops
as instead of printing a single chars
over and over with no line breaks, you can instead print the full number of spaces as a string with one call.
To see what I mean, I wrote your original code using this:
char = input("enter the char ")
rows = int(input("enter the number of inner rows "))
for r in range(rows, 0, -1):
print(' ' * 2 * (rows-r), end='')
print((char+' ') * (2*r+1))
see how much neater it is? Also, you can notice that in the second print of each row for the chars
, I used the calculation: 2*r +1
. This is what you need to convert this pattern:
3. * * * *
2. * * *
1. * *
0. *
to this one (as you requested):
3. *******
2. *****
1. ***
0. *
you can see that for each row of the second one, the number of chars
is 2 *
the row
+1
. So row 3
has 7
chars, row 2
has 5
etc.
If you wanted to, as you have gotten rid of the unnecessary for-loops
now, you could put both of the prints
in one statement:
print(' ' * 2 * (rows-r) + (char+' ') * (2*r+1))
however, the first may be considered neater and clearer so you might want to stick with the separate statements.
First off for this, we will need to input
two different chars
for the inner and outer triangles. This will allow us to differentiate which is which.
I think that the best way to do this would be to keep the print
statement which creates the spaces before the triangles as before, but modify how we draw the chars and their pattern.
This is what we want for an input of 4
rows:
0. .
1. ...
2. .....
3. .......
4. .*******.
5. ...*****...
6. .....***.....
7. .......*.......
notice how it would be simplest to split the printing
process in half. So for the top half just print a regular triangle, but for the bottom print one regular
, one flipped
and another regular
.
To do this, we want to loop through each of the 8
rows and check when we are half way through. If past halfway, we want the calculations for each smaller triangle to think they are at the top of the triangle, i.e. reset the row
count for them so when printing
row 4
, we calculate as if printing on row 0
. To achieve this, once past halfway, we need to modulo the row
variable by half of the total rows
(the total rows now being not what is entered, but double the entered amount as you can see we have a triangle with 8
rows but an inputted row value of 4
). This will give the intended effect of the triangles being half size of the total triangle.
Finally, one last thing to consider is that the center/inner triangle needs to be flipped as we have done before. As our row count is now going from 0
at the top downwards rather than the other way around, we need to change the calculation for that row to be rows - r
so it is flipped.
Taking all this into account, the final code may look something like:
innerChar = input("enter the inner char ")
outerChar = input("enter the outer char ")
rows = int(input("enter the number of inner rows "))
for r in range(2 * rows):
#print the white space on the left
print(' ' * 2 * (2 * rows-r), end='')
if r < rows:
#top triangle
print((outerChar+' ') * (2*r + 1))
else:
#working with the row modulo 2
r %= rows
#bottom three triangles
print((outerChar+' ') * (2*r + 1), end='')
print((innerChar+' ') * (2*(rows-r) - 1), end='')
print((outerChar+' ') * (2*r + 1))
Upvotes: 2
Reputation: 55469
One way to make this easier is to not worry about the spaces at first. Just generate the non-space symbols of each row, and save them into a list. Then at the end, determine the width of the biggest row, and use the str.center
method to print each row with the correct amount of space.
def tri(n, chars='*.'):
ic, oc = chars
outer = range(1, 2*n, 2)
# top triangle chars
rows = []
for w in outer:
rows.append(w * oc)
# lower triangles chars
inner = reversed(outer)
for u, v in zip(outer, inner):
a, b = u * oc, v * ic
rows.append(a + b + a)
# Get maximum row size
width = len(rows[-1])
#Print all the rows
for row in rows:
print(row.center(width))
# test
tri(5)
output
.
...
.....
.......
.*******.
...*****...
.....***.....
.......*.......
The characters to use are passed to tri
as a two character string, with a default of '*' for the inner char (ic
) and '.' for the outer char (oc
). But if you want to use other chars you can pass them, like this:
tri(4, '@o')
Upvotes: 0