# Printing bowTie pattern in efficient and pythonic way

I've posted code/library to GitHub for first time over here.

The code is pretty simple. It generates a BowTie pattern of given size and characters.

I did attempt to implement DP by calculating only half of shape matrix and getting its mirror image from matrix itself.

The code works fine. I do need help with someone analyzing to see if certain logic/lines can be done in more pythonic and efficient way [a.k.a. Code Review].

Any help is appreciated.

Source-Code

from __future__ import print_function

class BowTie(object):
def __init__(self, size=5, fill_value = '*', empty_value = ' '):
self.size = size
self.fill_value = fill_value
self.empty_value = empty_value

def  create_shape(self):
''' creates shape as per input values and returns list of list of values'''
star = self.fill_value
dot = self.empty_value
m = (self.size * 2) - 1 #Get center row

#get  top half list
th = []
for idx,k in enumerate(xrange(1,self.size+1)): #run through 1 - size
row = idx + 1
tmplst = []
if row % 2 != 0:
tmplst.append(i for i in xrange(1,row + 1) if i % 2 != 0)
tmplst.append(i for i in xrange(m, m-row, -1) if i % 2 != 0)
else:
tmplst.append(i for i in xrange(1,row + 1) if i % 2 == 0)
tmplst.append(i for i in xrange(m, m-row, -1) if i % 2 == 0)

#append each row value to  top half list.
th.append(sorted(set([j for i in tmplst for j in i])))

#create mirror-image of top half which is our bottom half
th = th + th[len(th) -2::-1]

def get_list(bound = self.size, alist = []):
''' expects upper bound and an integer list
returns a list of fill_values '''
tmp_list = []
for i in xrange(1,bound + 1):
tmp_list.append(star if i in alist else dot)
return tmp_list

#create list of * and blanks or as per fill and empty value
row_values = [get_list(bound = m, alist = i) for i in th]
return row_values

def print_shape(self):
''' print given list of list of values'''
for i in self.create_shape():
print(' '.join(i))


• Don't use a class, there's no need.
• You can remove the tmplst.append if you move the comprehensions into the th.append.

To do this you can use (i + idx) % 2 == 1 as the check. And tmplst = [xrange(1,row + 1), xrange(m, m-row, -1)].

• It doesn't make sense to build a set, to then convert it to a list. Sets have $O(1)$ lookup where lists have $O(n)$.

• You don't need get_list, just use a comprehension.

This can get something like:

def bow_tie(self, size=5, fill_value='*', empty_value=' '):
star = fill_value
dot = empty_value
center_row = size * 2 - 1
th = [
{
j
for nums in (
xrange(1, i + 2),
xrange(center_row, center_row - i - 1, -1)
)
for j in nums
if (j + i) % 2 == 1
}
for i in range(size)
]
th += th[len(th) -2::-1]

return [
' '.join([
star if i in indexes else dot
for i in range(1, size * 2)
])
for indexes in th
]


However, this isn't that good an approach. Instead you can make a list containing the pattern. And show a 'view'. The view that you want could be:

     *
**
***
****
*****
******


To achieve this, you can make the following list:

'     ******'


With the following moving view:

#     *######
##    **#####
###   ***####
####  ****###
##### *****##
######******#


You can also invert the view to get the other side of the bow tie. And so using the above, we just need to think of what the pattern of the list needs to be for your bowtie.

Since it's pretty much the same as the above, but with a space in-between the dots you could use something like:

'     * * * '


And to create that, just make the first n chars space, with the following n chars flip between space and star:

face = [empty_value] * (size - 1) + [fill_value, empty_value] * (size // 2 + 1)


After this combine the above slider, and chain the top and bottom starts, and you should get:

from itertools import chain

def bow_tie(size=5, fill_value='*', empty_value=' '):
face = [empty_value] * (size - 1) + [fill_value, empty_value] * (size // 2 + 1)
starts = chain(range(size), reversed(range(size-1)))
for i in starts:
yield ' '.join(face[i:i+size][::-1][:-1] + face[i:i+size])

• +1 for solving this in 7LOC and awesome use of sliding_window. I had to spend some time to understand your approach. I did implement sliding_window differently using islice as that's little easier for me. Pls. take a look at mods. – Anil_M Oct 30 '17 at 19:22