# Printing letters in order like a pyramid

There is this hackerrank question, where we need a rhombus of letters. As to my opinion it can be viewed as some fractal, or similar logic.

Well I solved the question, but I am obviously disappointed with the code I come up with. Actually when I started writing I knew how I would end-up and I was ready to ask a question here.

I am reluctant to share this code of mine but it is necessary, if I am to improve.

size = int(raw_input())
alphabet = "abcdefghijklmnopqrstuvwxyz"
def draw(size):
shape = "" # The answer
tmp_size = size # defining a temporary size variable to help with the solution
tmp_size -= 1
while tmp_size+1:
hyphen_count = (size-tmp_size) *2 - 2 # Needed hyphen count for the left-right of new_line
hypens = hyphen_count*"-" # Hyphens to be added

# The new line, the strange ranges I used was to get the correct letters in place. Probably needs simplifying.
new_line = "-".join([alphabet[abs(num)] for num in range(1-size,tmp_size-size+1) + range(size-tmp_size-1, size)])

# Draw one line if it is the first line
if tmp_size == size - 1:
shape = shape + new_line
# Draw to both top and bottom if it is not the first line.
else:
shape = hypens + new_line + hypens + "\n" + shape + "\n" + hypens + new_line + hypens
tmp_size -= 1
return shape
print draw(size)


I added many comments for easier evaluation of this badly-written code. So what I ask is:

• Dear users with algorithm experience, please help me find a better method if not the code itself. (Maybe a recursion ?)
• Dear programmers, please help me implement better python.
• Dear users that know everything, please teach me everything.

## 2 Answers

I propose a different method!
If you generate the center, and the size of the shape you can do the entire thing easily with str.format.

>>> '{0:-^16}'.format('yo')
'-------yo-------'


Simple.

The biggest problem is getting the diamond shape. But this can be done with ease.
For the amount of different letters you want per line it goes:

1, 2, 3, 4, 3, 2, 1


Where the character you want goes:

3, 2, 1, 0, 1, 2, 3


If you make a range that goes like the first, you can change it to the second by subtracting from 4 each time.

I'll define this range as:

def piramid_range(size):
return range(1, size) + range(size, 0, -1)


A quick run of size 4 gives us the correct output. And subtracting from 4 each time gives us the correct output too.

>>> piramid_range(4)
[1, 2, 3, 4, 3, 2, 1]
>>> [4 - i for i in piramid_range(4)]
[3, 2, 1, 0, 1, 2, 3]


and so adding this all together, with two comprehensions makes for a nice small function:

def draw(size):
fmt = '{{0:-^{size}}}'.format(size=4 * size - 3)
return '\n'.join(
fmt.format('-'.join([alphabet[size - s] for s in piramid_range(inner_size)]))
for inner_size in piramid_range(size)
)


And finally, as I think your separator character is quite ugly, I think adding the ability to change it would be nice. This is just replacing its two occurrences.

def draw(size, char='-'):
fmt = '{{0:{char}^{size}}}'.format(char=char, size=4 * size - 3)
return '\n'.join(
fmt.format(char.join([alphabet[size - s] for s in piramid_range(inner_size)]))
for inner_size in piramid_range(size)
)

print draw(4)
print
print draw(4, char=' ')


Which would have the following output:

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

d
d c d
d c b c d
d c b a b c d
d c b c d
d c d
d


Joe Wallis gave a much better algorithm, so I'll just give more general notes.

Instead of defining alphabet manually, you could import from the string module.

from string import ascii_lowercase as alphabet


You have a confusing pattern with tmp_size. The fact that you have to define while tmp_size+1 is a red flag. It would be better to write while tmp_size >= 0, which gives the same result. But also you don't need to use while loops to iterate over a set of numbers. for i in range(size - 1, -1, -1) will do what you want.

for i in range(size - 1, -1, -1):


Now there's no need for tmp_size, just refer to i as the current size.

You're recreating the string line twice in this line of code:

shape = hypens + new_line + hypens + "\n" + shape + "\n" + hypens + new_line + hypens


I recommend taking both the hyphen section and the algorithm and moving them to a new function

def get_line(i, size):


This way it's neater and separated out. You can just call it once to get the current line, then add it to shape as necessary.