9
\$\begingroup\$

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)

\$\endgroup\$
15
\$\begingroup\$

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.

General Comments

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}}")
\$\endgroup\$
4
  • 1
    \$\begingroup\$ def print_rangoli(n: int) -> None: Kindly explain this syntax. I couldn't get it. Why the None statement used here? @AJNeufeld \$\endgroup\$ Jun 18 '20 at 8:40
  • 4
    \$\begingroup\$ @GobindaDeb That is a type hint. \$\endgroup\$ Jun 18 '20 at 11:01
  • 2
    \$\begingroup\$ 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. \$\endgroup\$
    – AJNeufeld
    Jun 18 '20 at 13:30
  • 3
    \$\begingroup\$ strings are effectively just lists of characters — specifically, strings are sequences of characters. \$\endgroup\$
    – Reinderien
    Jun 23 '20 at 21:42
4
\$\begingroup\$

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
    print(padding + center + padding)

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.