Reputation: 97
How would you output n overlapping diamonds with each diamond having a height of 2n-1. Here are the required outputs for:
n = 3
* * *
* * * * * *
* * * * * * *
* * * * * *
* * *
n = 4
* * * *
* * * * * * * *
* * * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * *
* * * * * * * *
* * * *
n = 5
* * * * *
* * * * * * * * * *
* * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * *
* * * * * * * * * *
* * * * *
I have tried some code using loops. I have managed to output each shape correctly w.r.t the input n. However, I could not display the diamonds on a 'single line' only on multiple lines like this:
n = 3
*
* *
* * *
* *
*
*
* *
* * *
* *
*
*
* *
* * *
* *
*
This is the code I used:
n = int(input()) #for number of diamonds per row
height = 2*n - 1
for j in range(1, n + 1): #for printing h no. of diamonds
#from row 1 to middle row
for row in range(1, (height + 1)//2 + 1):
for spaces in range((height + 1)//2 - row): #print spaces per row
print(" ", end = "")
for stars in range((2*row) - 1): #print stars per row
if stars % 2 == 0:
print("*", end = "")
else:
print(" ", end = "")
print()
#from middle row to last row
for row in range((height + 1)//2 + 1, height + 1):
for spaces in range(row - (height + 1)//2):
print(" ", end = "")
for stars in range((height + 1 - row)*2 - 1):
if stars % 2 == 0:
print("*", end = "")
else:
print(" ", end = "")
print()
Upvotes: 4
Views: 280
Reputation: 39404
This is a way of printing the diamonds.
Each loop creates a line as a list of spaces and places part of each of the n
diamonds in it before printing the line in one go:
n = int(input()) #for number of diamonds per row
for row in range(n):
expanse = [' ']*(n+1)*(n-1)*2
spaces_before = n-row-1
stars = '* '*(row+1)
for diamond in range(n):
prefix = spaces_before + diamond*(n-1)*2
expanse[prefix : prefix+len(stars)-1] = stars
print(''.join(expanse))
for row in range(n-1):
expanse = [' ']*(n+1)*(n-1)*2
spaces_before = row+1
stars = '* '*(n-row-1)
for diamond in range(n):
prefix = spaces_before + diamond*(n-1)*2
expanse[prefix : prefix+len(stars)-1] = stars
print(''.join(expanse))
The output is as per the question.
Update: Replaced inner loop with list slicing
Upvotes: 2
Reputation: 818
This is my answer to the proposed problem:
class Diamond(object):
def __init__(self, size=3):
self.size = size
self.max_line_size = (size*2) + 1
self.max_line = [self.one_line(size)]
self.lines_below = map(self.one_line, range(size-1, 0, -1))
self.lines_above = self.lines_below[::-1]
self.lines = self.lines_above + self.max_line + self.lines_below
def __str__(self):
return "\n".join(self.lines)
def one_line(self, num_of_diamonds):
line_size = (num_of_diamonds * 2) + 1
line = list()
for i in range(1, line_size+1):
el = "*" if (i % 2 == 0) else " "
line.append(el)
str_line = "".join(line)
return (" " * ((self.max_line_size - line_size)/2)) + str_line + (" " * ((self.max_line_size - line_size)/2))
class Diamonds(object):
def __init__(self, size=3):
self.size = size
self.diamond = Diamond(size)
def __str__(self):
return "\n".join([i[:-1] + (i[2:-1]*(self.size-1)) for i in self.diamond.lines])
print(Diamonds(3))
print(Diamonds(4))
print(Diamonds(5))
I took a totally different approach from yours, but the main difference is in the method __str__
from Diamonds
class. My approach printed the diamonds in one line because I am generating a big string with all lines already generated and concatenated with an endline before calling print
. In your case it seems to me that you call print
whenever you finish generating each line of each diamond, and print
default behaviour is to endline after printing it's input.
Upvotes: 0
Reputation: 8059
How about this?
n = 4
for i in list(range(1, n+1)) + list(range(n-1, 0, -1)):
rowpattern = (' '*(n-i) + '* '*(i) + ' '*(n-i)) * n
print(rowpattern)
EDIT: Following comment below, this is more accurate:
n = 4
for i in list(range(1, n)) + list(range(n, 0, -1)):
rowpattern = ' ' * (n-i) + ('* ' * (i if i!=n else i-1) +
' ' * (2 * (n - i) - 2)) * n + '*' *(1 if i==n else 0)
print(rowpattern)
Upvotes: 2
Reputation: 10809
def print_diamonds(n):
from functools import lru_cache
number_of_peaks = n
step_size = (n * 2) - 2
@lru_cache(maxsize=n)
def get_star_indecies(y):
star_index_offset = 2 * y
begin = star_index_offset
end = (number_of_peaks * step_size) + begin
star_indecies = {*range(begin, end, step_size)}
if y == 0:
return star_indecies
else:
return star_indecies | get_star_indecies(y-1)
for iteration in range(n*2-1):
y = -abs(iteration-(n-1))+(n-1)
star_indecies = get_star_indecies(y)
line_length = max(star_indecies) + 1
space_offset = n-y-1
space_padding = " " * space_offset
line = space_padding
for index in range(line_length):
line += [" ", "*"][index in star_indecies]
print(line)
def main():
print_diamonds(5)
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
Upvotes: 0