DEV Community


Discussion on: Daily Challenge #2 - String Diamond

shoupn profile image
Nick Shoup

Refactored slightly, used range function on the initial passed in value, instead of adding 1, but I came across your solution which both checked for negative numbers and how to elegantly print the row in one line. I also through in a check for even values at the beginning.

def diamond(width):
    if width % 2 == 0:
        print("width needs to be odd")
    for num in range(width):
        num = num - (width//2)
        if num < 0:
            num = -num
        print(' ' * num + '*' * (width - num *2) + ' ' * num)

iarmankhan profile image
Arman Khan

WOW! 😍

orenovadia profile image

I would like to add:
1) Making do some of the dirty work
2) Using ranges (and chain) to iterate up and down instead of keeping a state on num

from itertools import chain

def diamond(n): 
    if n <=0 or n % 2 == 0:
        raise ValueError('n must be odd and positive') 
    for i in chain(range(1, n + 1, 2), reversed(range(1, n, 2))): 
        print(('*' * i).center(n)) 


It might be more readable to have two loops instead of using chain but I like chaining more because I don't need to repeat the print

Thread Thread
highcenburg profile image
Vicente G. Reyes

Is this fast too?

Thread Thread
orenovadia profile image

I wouldn't worry about it too much, since print requires IO, it is by far the bottleneck.

For the rest of the utilities that I used: range, chain, and they are all implemented in C if you are using the standard CPython (should be fast).

To avoid the IO, let's compare the two functions as generators of strings (I replaced the print with yield (('*' * i).center(n)) for both my implementation and Nicks:

In [39]: %timeit tuple(my_diamond(11))                                                                                                                                                                                 
3.59 µs ± 37.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [40]: %timeit tuple(nicks_diamond(11))                                                                                                                                                                           
4.66 µs ± 69.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Seems like mine is slower than Nicks.
However, on my machine, a single print statement takes about 4.17us, which is almost as long as diamond(11) takes without any prints!