Skip to content

S3Q2 · Hollow Square Ring Pattern

⚡ Quick Reference

Type: Full I/O problem

Core idea: Three row types -- top border, middle (border only), bottom border. Middle rows end with # so no trailing spaces.

n = int(input())
for i in range(n):
    if i == 0 or i == n - 1:
        print('#' * n)
    else:
        print('#' + ' ' * (n - 2) + '#')

Key rules: - Row 0 and row n-1: # × n - Every middle row: # + (n-2) spaces + # - No trailing spaces -- middle rows end with #, not a space


Problem Statement

Problem

Given n, print an n × n hollow square using #. Only the border is filled; interior cells are spaces. No trailing spaces after the last # on any row. n >= 2 always.

Examples:

Input
4
Output
####
#  #
#  #
####
Input
5
Output
#####
#   #
#   #
#   #
#####
Input
2
Output
##
##

Understanding the problem

Every row falls into one of three types:

Row Condition Content
Top i == 0 # × n
Middle 0 < i < n-1 # + (n-2) spaces + #
Bottom i == n-1 # × n

For n = 4, that gives:

####        ← top border
#  #        ← middle (n-2 = 2 spaces between the #s)
#  #        ← middle
####        ← bottom border

No trailing spaces because middle rows end with #

The hollow middle row is '#' + ' ' * (n-2) + '#'. The rightmost character is always #, so there is nothing to strip. A naive approach of building an n-wide string with spaces and replacing corners can leave trailing spaces -- building the string directly avoids this.

n = 2 edge case

When n = 2 there are no middle rows (rows 1 to n-2 is an empty range). Both rows 0 and 1 are border rows, so the output is just two ## lines. The loop handles this automatically without any special case.


Solution approaches

n = int(input())
for i in range(n):
    if i == 0 or i == n - 1:
        # Top and bottom border: all hashes
        print('#' * n)
    else:
        # Middle rows: hash, interior spaces, hash
        interior = ' ' * (n - 2)
        print('#' + interior + '#')
n = int(input())
border = '#' * n
middle = '#' + ' ' * (n - 2) + '#'
rows   = [border] + [middle] * (n - 2) + [border]
print('\n'.join(rows))
n = int(input())
row = lambda i: '#'*n if i in (0, n-1) else '#'+' '*(n-2)+'#'
print('\n'.join(row(i) for i in range(n)))

Key takeaways

01

Three-type row classification

Pattern printing usually reduces to classifying each row. Here the three types are: top border, middle (hollow), bottom border. The condition i == 0 or i == n-1 handles both borders in one branch.

02

Build strings directly to avoid trailing spaces

Constructing the middle row as '#' + ' '*(n-2) + '#' guarantees no trailing spaces. Avoid building an all-space string and then replacing positions -- that leaves spaces at the end if you forget to strip.

03

Precompute repeated strings

The Pythonic approach builds border and middle once, then assembles the full list with [border] + [middle]*(n-2) + [border]. Cleaner than computing the same string in every loop iteration.