# Alphabet Rangoli

I have written alphabet rangoli code in python and would like to get it reviewed. The goal is to print concentric diamond shapes made of letters, with "a" at the center, "b" forming the next layer, then "c", etc.

Any comments on making it more logical or concise shall be appreciated.

import math

# input the size of alphabet rang oli
def print_rangoli(size):
totalHeight = (2 * size) - 1
totalWidth = (2 * totalHeight) - 1
numberOfAlphabets = 1
numberOfDashes = (totalWidth - numberOfAlphabets) // 2
# initialize a list of alphabets
alphabets = "a b c d e f g h i j k l m n o p q r s t u v w x y z".split(" ")
# run a for loop totalHeight number of times
for i in range(1, totalHeight + 1):
if i <= math.ceil(totalHeight / 2):
print("-" * numberOfDashes, end="")
listIndex = size - 1
for k in range(math.ceil(numberOfAlphabets / 2)):
if size == 1:
print(alphabets[listIndex])
else:
print(alphabets[listIndex] + "-", end="")
listIndex -= 1
listIndex += 1
for k in range(math.floor(numberOfAlphabets / 2)):
listIndex += 1
if i == math.ceil(totalHeight / 2) and k == math.floor(numberOfAlphabets / 2) - 1:
print(alphabets[listIndex], end="")
else:
print(alphabets[listIndex] + "-", end="")

print("-" * (numberOfDashes - 1))
if i != math.ceil(totalHeight / 2):
numberOfAlphabets += 2
numberOfDashes -= 2
else:
numberOfDashes += 2
numberOfAlphabets -= 2
print("-" * numberOfDashes, end="")
listIndex = size - 1
for k in range(math.ceil(numberOfAlphabets / 2)):
print(alphabets[listIndex] + "-", end="")
listIndex -= 1
listIndex += 1
for k in range(math.floor(numberOfAlphabets / 2)):
listIndex += 1
print(alphabets[listIndex] + "-", end="")

print("-" * (numberOfDashes - 1))

if __name__ == "__main__":
size = int(input())
print_rangoli(size)


• What is alphabet rangoli, please? I can infer that it's some pattern, but an explanation can't hurt. This raises on n > 26, which probably should be handled. May 5, 2022 at 16:53
• I would love to see example output here May 6, 2022 at 23:46
• Just a comment on the variable name alphabets, numberOfAlphabets, etc. This should be letters and numberOfLetters. In English, "A" is a letter, "B" is a letter and A,B, and C are 3 letters. There is only one alphabet, ABCDEFGHIJKLMNOPQRSTUVWXYZ. May 6, 2022 at 23:49

You can simplify the code by a lot.

The first simple change is that you don't need to define the alphabet this way:

alphabets = "a b c d e f g h i j k l m n o p q r s t u v w x y z".split(" ")


Your code would work just fine if you treat a string as indexable:

alphabets = "abcdefghijklmnopqrstuvwxyz"


Simplifying further, you can take advantage of the builtin module:

from string import ascii_lowercase as alphabets


Instead of tediously figuring out where to put the "-" characters as left padding, right padding, and internally, you can use str.center(width, '-') to do the padding, and '-'.join('cbabc') to obtain "c-b-a-b-c". Putting those two techniques together, then, you could write

print('-'.join('cbabc').center(11, '-'))


… to obtain

--c-b-a-b-c--


You don't need to do so much arithmetic to calculate numberOfDashes and numberOfAlphabets. I'd just compose the middle row as a string, then call len(…) to have Python tell you how wide the layout has to be.

The way you've structured your code, you have four cases: if i <= math.ceil(totalHeight / 2): to test whether you are in the top half or the bottom half, and for each of those cases, a for k in … loop to handle the left side, and another for k in … loop to handle the right.

Instead of all that, I suggest using the abs() function to help you do a symmetric iteration.

## Suggested solution

from string import ascii_lowercase

def seq(n, i):
return '-'.join(
ascii_lowercase[i + abs(j)]
for j in range(i - n, n - i + 1)
)

def rangoli(n):
width = len(seq(n, 0))        # Pad everything to match the width of the center row
return '\n'.join(
seq(n, abs(i)).center(width, '-')
for i in range(-n, n + 1)
)

if __name__ == "__main__":
size = int(input())
print(rangoli(size - 1))


In order to print all rows you could use two cycles:

• an increasing cycle to print the first half rows
• a decreasing cycle to print the second half rows

In order to print a single row, you can notice that:

• the content has letters concatenated to their own reverse, with exception of the middle one (e.g. edcb + a + bcde)
• each space is printed as a hyphen
• each letter/space is separated by a hyphen

Given this situation, what you can do is first generate the content (letters+spaces) and then use Python join operation to generate your rangoli row:

# input the size of alphabet rang oli
def print_rangoli(size):
alphabet = "abcdefghijklmnopqrstuvwxyz"

# extracting letters to use from alphabet
letters = alphabet[:size]

# variables used in the cycles
dashes  = ''
content = ''

# generating first half
for i in range(1, size+1, 1):
dashes  = '-'*(size-i)
content = letters[:i][::-1] + letters[1:i]
print('-'.join(dashes + content + dashes))

# generating second half
for i in range(size-1, 0, -1):
dashes  = '-'*(size-i)
content = letters[:i][::-1] + letters[1:i]
print('-'.join(dashes + content + dashes))

if __name__ == "__main__":
size = int(input())
print_rangoli(size)


This solution also handles borderline cases related to the size range domain [0,26]. If you want to handle cases related to size < 0 or size > 26, you can do that with some checks at the beginning of the function.