HackerRank: Alphabet Rangoli Notes
Background
This article was written down when I was doing the Python challenge on HackerRank: Alphabet Rangoli. Although I passed all the tests quickly, my solution looked dirty and not clean enough. Thus I tried to simplify my solution after getting some insights from the Discussion and Editorial sections.
Problem
The problem gives you a number N
named size
where \( 0 < size < 27 \). You are required to output an ASCII art like this:
#size 3
----c----
--c-b-c--
c-b-a-b-c
--c-b-c--
----c----
#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--------
#size 10
------------------j------------------
----------------j-i-j----------------
--------------j-i-h-i-j--------------
------------j-i-h-g-h-i-j------------
----------j-i-h-g-f-g-h-i-j----------
--------j-i-h-g-f-e-f-g-h-i-j--------
------j-i-h-g-f-e-d-e-f-g-h-i-j------
----j-i-h-g-f-e-d-c-d-e-f-g-h-i-j----
--j-i-h-g-f-e-d-c-b-c-d-e-f-g-h-i-j--
j-i-h-g-f-e-d-c-b-a-b-c-d-e-f-g-h-i-j
--j-i-h-g-f-e-d-c-b-c-d-e-f-g-h-i-j--
----j-i-h-g-f-e-d-c-d-e-f-g-h-i-j----
------j-i-h-g-f-e-d-e-f-g-h-i-j------
--------j-i-h-g-f-e-f-g-h-i-j--------
----------j-i-h-g-f-g-h-i-j----------
------------j-i-h-g-h-i-j------------
--------------j-i-h-i-j--------------
----------------j-i-j----------------
------------------j------------------
The center should be the first alphabet letter a
, and the boundary should be the \( N^{th} \) alphabet letter. For example, j
is the 10th alphabet letter.
Analysis and Solution
Initial Thought
My initial thought was something like this:
def print_rangoli(size):
l = "abcdefghijklmnopqrstuvwxyz"
result = []
for i in range(size,0,-1):
s = l[size-i:size][::-1]+l[size-i+1:size]
s = "-".join(s)
result.append(s)
for i in result[::-1]:
print(i.center(4*size-3,'-'))
for j in result[1:]:
print(j.center(4*size-3,'-'))
I typed an alphabetical order list l
by myself 😂. (turns out you don't need to do it yourself, will explain later :D)
My idea is to print out the middle line and join it with the -
because other lines can be viewed as a shortened version of the middle one.
For the following part:
for i in range(size,0,-1):
s = l[size-i:size][::-1]+l[size-i+1:size]
s = "-".join(s)
result.append(s)
print(s)
The corresponding output will be:
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
Then we store them into a list called result
and print them by using the center() method. But it is a bit tedious.
(If you are not familiar with the center() method, you can read it in my another note.)
Also, the following technique is called Extended Slices. It is used to make a copy of the same list in reverse order.
result[::-1]
How to calculate the 4n-3?
How can we find out the number of characters in the middle line? First, the number of letters is (n + (n-1)) = 2n-1
and adding the number of -
s: 2n-1 + (2n-1-1) = 4n-3
.
Optimized Solution
After I read the Discussion and Editorial sections, I modified my solution to this:
def print_rangoli(size):
# your code goes here
l = "abcdefghijklmnopqrstuvwxyz"
result = []
for i in range(size):
s = l[i:size][::-1]+l[i+1:size]
s = "-".join(s).center(4*n-3,'-')
result.append(s)
print("\n".join(result[::-1]+result[1:]))
I used the center() while I was joining the string. Also, use "\n" to join the strings in the result
. Besides, I changed range(size,0-1)
to range(size)
because my initial thought had a bit problem here.
And actually... we don't need to type the list ourselves 😂:
import string
l = string.ascii_lowercase
def print_rangoli(size):
result = []
for i in range(size):
s = l[i:size][::-1]+l[i+1:size]
s = "-".join(s).center(4*n-3,'-')
result.append(s)
print("\n".join(result[::-1]+result[1:]))
Reference
- HackerRank: Alphabet Rangoli 笔记 (My Chinese Blog)
I hope this article helps!