Alphabet Rangoli Challenge

The question is about printing alphabets in a rangoli pattern of size/dimension input by the user.

Example:

size 3

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


The picture contains details about the challenge

OR

https://www.hackerrank.com/challenges/alphabet-rangoli/problem

Sample Code:

n = int(input('Enter a size: '))

alpha = ['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']

for j in range(0, n-1):
ls_1 = str(''.join(alpha[n-1:abs(n-(j+2)):-1]))
ls_1 = ls_1 + ls_1[-2::-1]
ls = str('-'.join(ls_1))
print('-' * (((n - j) * 2) - 2) + ls + '-' * (((n - j) * 2) - 2))

ls_1 = str(''.join(alpha[n-1::-1]))
ls_1 = ls_1 + ls_1[-2::-1]
ls = str('-'.join(ls_1))
print(ls)

for j in range(n-2, -1, -1):
ls_2 = str(''.join(alpha[n-1:abs(n-(j+2)):-1]))
ls_2 = ls_2 + ls_2[-2::-1]
ls_s = str('-'.join(ls_2))
print('-' * (((n - j) * 2) - 2) + ls_s + '-' * (((n - j) * 2) - 2))


Sample Output:

Enter a size: 5
--------e--------
------e-d-e------
----e-d-c-d-e----
--e-d-c-b-c-d-e--
e-d-c-b-a-b-c-d-e
--e-d-c-b-c-d-e--
----e-d-c-d-e----
------e-d-e------
--------e--------


Is the above code that I have done...is it a good code to say? Also, I couldn't find any other way to solve the problem. (I am a beginner in Python)

Use built-ins

alpha = ['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']


This is a very verbose and error-prone way of getting all of the ASCII lowercase letters.

from string import ascii_lowercase as alpha


will give approximately the same result. It is a string, instead of a list, but Python strings are effectively just lists of characters. In particular, alpha[0] will be 'a' and alpha[25] will be 'z'.

Unnecessary str()

The result of a ''.join(...) call will be a string. Wrapping this in a str(...) call is pointless.

Unnecessary abs()

for j in range(0, n-1) means that j will always be less than n-1. In other words:

$$j \le n - 2$$

Consider, abs(n-(j+2)): $$j \le n - 2$$ $$j + 2 \le n$$ $$n - (j+2) \ge 0$$ In other words, the abs(...) is unnecessary, and just adds confusion.

Follow PEP-8 guidelines (spaces around operators, etc). Use functions. Use a main-guard.

Reworked & Simplified Code

from string import ascii_lowercase

def print_rangoli(n: int) -> None:

alpha = ascii_lowercase[:n]

for row in range(- n + 1, n):
row = abs(row)
dashes = "-" * (2 * row)
print(dashes + "-".join(alpha[:row:-1] + alpha[row:]) + dashes)

if __name__ == '__main__':
n = int(input("Enter a size: "))
print_rangoli(n)



Format Specification Mini-Language

Python's format statement (and f-strings) use a format specification mini-language. This allow you substitute values into a larger string in fixed-width fields, with your choice of alignment and fill characters. Here, you'd want centre alignment, with '-' for the fill character.

For example, f"{'Hello':-^11}" is a f-string, which places the string 'Hello' into a field 11 characters wide, centre justified (^), with '-' used as a fill character. Producing '---Hello---'. Instead of a hard-coded width (11 in the above example), we can use a computed {width} argument.

Using this, we can further "simplify" (for some definition of simplify) the print_rangoli function:

def print_rangoli(n: int) -> None:

width = n * 4 - 3
alpha = ascii_lowercase[:n]

for row in range(- n + 1, n):
row = abs(row)
print(f"{'-'.join(alpha[:row:-1] + alpha[row:]):-^{width}}")

• def print_rangoli(n: int) -> None:  Kindly explain this syntax. I couldn't get it. Why the None statement used here? @AJNeufeld Commented Jun 18, 2020 at 8:40
• @GobindaDeb That is a type hint. Commented Jun 18, 2020 at 11:01
• Functionally, this is no different from def print_rangoli(n):, but with the benefit that Python Type Checkers can warn you if you accidentally write x = print_rangoli(True) that a) you are not passing an integer argument to the function, and b) nothing will be returned to assign to x. Syntactically there is nothing wrong with that statement; you pass 1 argument to a function expecting 1 argument. Functionally, there is nothing wrong with it either; it will print a rangoli of size 1 & assign None to x. But logically it is an error. The seatbeats are optional… and mostly decorative. Commented Jun 18, 2020 at 13:30
• strings are effectively just lists of characters — specifically, strings are sequences of characters. Commented Jun 23, 2020 at 21:42

I think the general algorithm is OK, but you have a lot of repetition in your code! Also avoid writing out the alphabet by hand when you could have Python generate it for you. Here is the code without repetition:

n = int(input('Enter a size: '))

alpha = [chr(ord('a') + i) for i in range(0, 26)]

for k in range(1 - n, n):
j = n - abs(k)
center = '-'.join(alpha[n-1:n-j:-1] + alpha[n-j:n])
padding = '-' * abs(k) * 2

I used a single for-loop that goes from 1-n to n, so this covers both the upper and lower half, and I also made it so you don't have to treat the center line as a special case.