Reputation: 113
I have written the following code and it runs but I am using 4 for loops and I would like to know if there is more effective way to write this code.
n = int(input('Please Enter the highest number \n'))
col = 2*n-1
for i in range(1, n+1):
for j in range(1, col+1):
if j >= i and j <= col-i+1:
print(n-i+1, end=' ')
elif j < i:
print(n+1-j, end=' ')
else:
print(j+1-n, end=' ')
print()
for i in range(n-1, 0, -1):
for j in range(1, col+1):
if j >= i and j <= col - i + 1:
print(n-i+1, end=' ')
elif j < i:
print(n + 1 - j, end=' ')
else:
print(j + 1 - n, end=' ')
print()
Upvotes: 1
Views: 677
Reputation: 341
You could find the position relative to the center (di, dj)
, and then use its largest component as the label for that cell:
n = int(input('Please Enter the highest number \n'))
col = 2 * n
for i in range(1, col):
row = []
for j in range(1, col):
di, dj = abs(n-i), abs(n-j)
row.append(max(di,dj) + 1)
print(' '.join(str(x) for x in row))
Upvotes: 2
Reputation: 31
Breaking this down into a few logical obsevations.
So we know that to follow DRY principle, we only need to generate one corner of the pyramid, and then we simply copy it to the other 3 corners.
(assuming use of pure python 3.x only, without libraries such as numpy)
def print_pyramid(n=4):
"""Print a symmetrical pyramid of numbers descending from n"""
# Calculate bottom half of grid
bottom = []
for j in range(n):
row = [max(i, j + 1) for i in range(1, n + 1)]
row = row[::-1][:-1] + row
bottom.append(row)
# Invert bottom to get top
rows = bottom[::-1][:-1] + bottom
# Print formatted
for row in rows:
row_str = [str(i) for i in row]
print(f"{' '.join(row_str)}")
print_pyramid(4)
This is definitely not the most efficient method (see recursive functions), but it is fairly quick and pythonic.
Bottom Right corner
First we generate an array of numbers, 1 => n:
[i for i in range(1, n + 1)]
[1, 2, 3, 4]
Then we loop n times to generate this for each row (j), but replace any values lower than j using max:
for j in range(n):
row = [max(i, j+1) for i in range(1,n+1)]
[1, 2, 3, 4]
[2, 2, 3, 4]
[3, 3, 3, 4]
[4, 4, 4, 4]
Bottom Left Corner (~mirror image)
First we select the row elements in reverse with slice notation [::-1]
Then we remove the last element [:-1]
row = [max(i, j+1) for i in range(1,n+1)]
row[::-1][:-1]
[4, 3, 2]
[4, 3, 2]
[4, 3, 3]
[4, 4, 4]
Top Half Now we create the top half using the same slicing technique to reverse and select from our existing nested array.
bottom[::-1][:-1]
[4, 4, 4, 4, 4, 4, 4]
[4, 3, 3, 3, 3, 3, 4]
[4, 3, 2, 2, 2, 3, 4]
Finally, we print our full array with string formatting
for row in rows:
row_str = [str(i) for i in row]
print(f"{' '.join(row_str)}")
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
P.S. Please don't cheat on your homework assignments ;)
Upvotes: 1
Reputation: 1837
from itertools import chain
...
for i in chain(range(1, n + 1), range(n - 1, 0, -1)):
...
i <= j <= col - i + 1
Upvotes: 0