Print concentric rectangular patterns

I am solving interview questions from here.

Problem : Print concentric rectangular pattern in a 2d matrix. The outermost rectangle is formed by A, then the next outermost is formed by A-1 and so on. You will be given number as an argument to the function you need to implement, and you need to return a 2D array.

Example 1: Input: A = 4.

        Output:

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


How can I make this code better?

def pretty_print(num):

m = n = 2*num -1 ##    m x n matrix , length of each row and column
k = 0 # row start counter
l = 0 # column start counter
i = 0 # iterator

matrix = [[0 for _ in range(n)] for _ in range(m)]

while k < m and l < n :
#insert the first row
for i in range(l, n) :
if matrix[k][i] == 0:
matrix[k][i] = num   # row index constt, change values in columns

k += 1   # first row printed, so increment row start index

#insert the last column
for i in range(k, m) :
if matrix[i][n-1]==0:
matrix[i][n-1] = num   # column index constt, change values in rows
n -= 1   # last column printed, so decrement num of columns

#insert the last row
if (k<m):   #  if row index less than number of rows remaining
for i in range(n-1, l-1, -1):
if matrix[m-1][i] == 0:
matrix[m-1][i] = num   # row index constt, insert in columns
m -= 1   # last row printed, so decrement num of rows

#insert the first column
if (l<n):    #  if column index less than number of columns remaining
for i in range(m-1, k-1, -1):
if matrix[i][l] == 0:
matrix[i][l] = num # column index constt, insert in rows
l += 1      # first column printed, so increment column start index

num -= 1    # all elements of value A inserted , so decrement

return matrix

print pretty_print(6)


Simplify

I find the logic a bit complicated. It could be simpler:

• Loop from -A to +A, let's call the loop variable n
• Take the absolute value of n
• Generate the values in the row:
• Loop from -A to +A, let's call the loop variable m
• Use the maximum of abs(n) + 1 and abs(m) + 1

Like this:

def pretty_print(num):
def print_line(n):
low = abs(n)
print(' '.join(str(max(low + 1, abs(i) + 1)) for i in range(-num + 1, num)))

for i in range(-num + 1, num):
print_line(i)


Testing

Doctests are awesome, I recommend to use them. Here's the complete solution with doctests, you can run this with python -mdoctest pretty_print.py:

#!/usr/bin/env python

def pretty_print(num):
"""
>>> pretty_print(1)
1

>>> pretty_print(2)
2 2 2
2 1 2
2 2 2

>>> pretty_print(6)
6 6 6 6 6 6 6 6 6 6 6
6 5 5 5 5 5 5 5 5 5 6
6 5 4 4 4 4 4 4 4 5 6
6 5 4 3 3 3 3 3 4 5 6
6 5 4 3 2 2 2 3 4 5 6
6 5 4 3 2 1 2 3 4 5 6
6 5 4 3 2 2 2 3 4 5 6
6 5 4 3 3 3 3 3 4 5 6
6 5 4 4 4 4 4 4 4 5 6
6 5 5 5 5 5 5 5 5 5 6
6 6 6 6 6 6 6 6 6 6 6
"""

def print_line(n):
low = abs(n)
print(' '.join(str(max(low + 1, abs(i) + 1)) for i in range(-num + 1, num)))

for i in range(-num + 1, num):
print_line(i)

pretty_print(6)


Style

There are some minor style issues with the posted code. I suggest to follow the PEP8 guidelines.