# Draw a hollow square of # with given width

I got this challenge from Codingame and am curious about better solutions than mine:

Given a width via standard input draw a hollow square of '#' in given width and length.

Example:

5 results in

#####
#   #
#   #
#   #
#####


I used python to solve this so i am particulary interested in other python code. But please feel free to post your solution in any language you want.

• What if input is 0 or 1? – Karl Napf Nov 7 '16 at 14:27
• Related, though this might be different enough to not be a dupe. – AdmBorkBork Nov 7 '16 at 14:31
• Welcome to PPCG! For future questions, I encourage you to use the Sandbox where you can get meaningful feedback on a challenge before posting it to the main page. – AdmBorkBork Nov 7 '16 at 14:31
• Reading through the answers, I'm not convinced it's a dupe. Most of the answers here (golfing and regular languages) are roughly half the size of the answers on "Print N Squared." – AdmBorkBork Nov 7 '16 at 16:43
• This is absolutely a duplicate. Solutions from the other challenge can be trivially modified to be valid and competitive here. – user45941 Nov 8 '16 at 10:42

## Pyke, 11 bytes

ttDd*n+*.X#


Try it here!

ttDd*n+*    - a square of spaces n-2*n-2 big
.X# - surround in #


# Charcoal, 6 bytes

Code:

ＮβＢββ#


Explanation:

Ｎβ        # Get input from the command line and store into β
Ｂ      # Draw a hollow box with...
β     #  Width β
β    #  Height β
#   #  Filled with the character '#'
# Implicitly output the box


Try it online!

• I was trying to figure out how to read input in Charcoal. Now I know :) – Emigna Nov 7 '16 at 15:22
• @Emigna Note that Ｎ can also be used in an expression, like int(input()) in Python. If this challenge were "draw a hollow rectangle with given width and height," the solution could be ＢＮＮ#. – DLosc Nov 8 '16 at 1:50
• Does Charcoal use a non-UTF8 charset? – OldBunny2800 Nov 8 '16 at 2:49
• That looks like 6 characters, not 6 bytes. β is in plenty of alternate 8-bit character sets, but I'm dubious about Ｎ(which is not N) – Sparr Nov 8 '16 at 3:22
• @Sparr Charcoal uses its own codepage. – Conor O'Brien Nov 8 '16 at 4:25

# MATL, 12 bytes

:G\1>&*~35*c


Try it online!

### Explanation

:     % Input n implicitly. Push range [1 2 ... n]
% STACK: [1 2 3 4 5]
G     % Push n again
% STACK: [1 2 3 4 5], 5
\     % Modulo
% STACK: [1 2 3 4 0]
1>    % Does each entry exceed 1?
% STACK: [0 1 1 1 0]
&*    % Matrix with all pair-wise products
% STACK: [0 0 0 0 0;
0 1 1 1 0;
0 1 1 1 0;
0 1 1 1 0;
0 0 0 0 0]
~     % Negate
% STACK: [1 1 1 1 1;
1 0 0 0 1;
1 0 0 0 1;
1 0 0 0 1;
1 1 1 1 1]
35*   % Multiply by 35
% STACK: [35 35 35 35 35;
35  0  0  0 35;
35  0  0  0 35;
35  0  0  0 35;
35 35 35 35 35]
c     % Convert to char. 0 is interpreted as space. Display implicitly
% STACK: ['#####';
'#   #';
'#   #';
'#   #';
'#####']


# Jolf, 8 bytes

,ajj"###
,ajj      draw a box with height (input) and width (input)
"###  with a hash border

• The right tool for the job :) – Emigna Nov 7 '16 at 15:05
• Out of curiosity, why are three # required? – Kevin Cruijssen Nov 7 '16 at 15:54
• @KevinCruijssen Each specify the horizontal struts, vertical struts, and corner pieces. – Conor O'Brien Nov 7 '16 at 16:50

## Python 2, 62 54 bytes

f=lambda n:'#'*n+'\n#%s#'%(' '*(n-2))*(n-2)+'\n'+'#'*n


Returns #\n# when the input is 1

55 Bytes version that prints

def f(n):a=n-2;print'#'*n,'\n#%s#'%(' '*a)*a,'\n'+'#'*n


62 Bytes version that works for any input:

f=lambda n:'#'*n+'\n#%s#'%(' '*(n-2))*(n-2)+('\n'+'#'*n)*(n>1)

• You do not have to say f= unless you use it––which you don't. – Daniel Nov 7 '16 at 18:57
• @Dopapp I know, but I think it's more fair that way (in comparison to full functions / programs) – Rod Nov 8 '16 at 11:25
• @Rod Your choice, but we have a policy about anonymous functions that allows them. – Erik the Outgolfer Nov 8 '16 at 12:50

# COW, 426405348 330 bytes

MoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMMMmoOMMMMoOMoOMoOMoOMoOMoOMoOMoOMoO
MoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMMMmoOMMMMoOMoOMoOmoOoomMMM
moOMMMMOOmOomOoMoomoOmoOMOomoomOoMMMmoOMMMMOoMOoMOOmOomOomOomOoMoo
moOmoOMoomoOMMMmoOmoOMMMMOoMOoMOOmOomOomOomOoMoomoOmoOmoOmoOMOomoo
mOomOomOoMoomoOmoOMOomoomOomOomOomOoMoomoOmoOmoOMOOmOoMoomoOMOomoo


Try it online! Change the number in the second line to any number to change the output.

The COW interpreter that I'm using here was written in Perl (and is newer than this challenge), but you can still get the same result by inputting the code here.

### Explanation

; Note: [n] means "value stored in the nth block of memory".
MoOMoOMoOMoOMoOMoOMoOMoOMoOMoO                                                  ;Stores 10 in .  10 is the code point for carriage return
MMMmoOMMMMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoOMoO     ;Stores 32 in .  32 is the code point for whitespace
MMMmoOMMMMoOMoOMoO                                                              ;Stores 35 in .  35 is the code point for #
moOoom                                                                          ;Reads STDIN for an integer, and stores it in 
MMMmoOMMM                                                                       ;Copies  into 
MOO                                                                             ;Loop as long as  is non-zero
mOomOoMoo                                                                   ;Navigate to  and print the character with that code point
moOmoOMOo                                                                   ;Navigate to  and decrement
moo                                                                             ;End loop
mOoMMMmoOMMMMOoMOo                                                              ;Copy  into  and decrement  twice
MOO                                                                             ;Loop as long as  is non-zero
mOomOomOomOoMoo                                                             ;Navigate to  and print the character with that code point
moOmoOMoo                                                                   ;Navigate to  and print the character with that code point
moOMMMmoOmoOMMMMOoMOo                                                       ;Navigate to  and copy it into , then decrement  twice
MOO                                                                         ;Loop as long as  is non-zero
mOomOomOomOoMoo                                                         ;Navigate to  and print the character with that code point
moOmoOmoOmoOMOo                                                         ;Navigate to  and decrement
moo                                                                         ;End loop
mOomOomOoMoo                                                                ;Navigate to  and print the character with that code point
moOmoOMOo                                                                   ;Navigate to  and decrement
moo                                                                             ;End loop
mOomOomOomOoMoo                                                                 ;Navigate to  and print the character with that code point
moOmoOmoO                                                                       ;Navigate to 
MOO                                                                             ;Loop as long as  is non-zero
mOoMoo                                                                      ;Navigate to  and print the character with that code point
moOMOo                                                                      ;Navigate to  and decrement
moo                                                                             ;End loop


# Python 2, 59 58 bytes

n=i=input()
while i:print'#%s#'%((' #'[i%n<2])*(n-2));i-=1


repl.it

Note: An input of 1 produces an output of ##, but a hollow square would never be produced for an input less than 3, so I guess this is fine.

# Java 7, 113112 110 bytes

String c(int n){String r="";for(int i=n,j;i-->0;r+="\n")for(j=0;j<n;r+=i*j<1|n-i<2|n-j++<2?"#":" ");return r;}


1 byte saved thanks to @OlivierGrégoire;
2 bytes saved thanks to @cliffroot.

Derived solution based on my Creating a Crossed Square answer.

Try it here.

• Could you shave a byte by doing the following for(int i=n,j;i-->0;r+="\n")? Since we don't care which is the bottom line or the top one, it doesn't make any sense to keep that order, right? – Olivier Grégoire Nov 8 '16 at 12:45
• @OlivierGrégoire Thanks! I've also edited it in my Creating a Crossed Square answer, since there the same could be done. – Kevin Cruijssen Nov 8 '16 at 12:56

## PowerShell v2+, 48 47 bytes

param($n)($z='#'*$n--);,("#$(' '*--$n)#")*$n;$z  -1 byte thanks to JohnLBevan Takes input $n, sets $z as $n hashmarks, with $n post-decremented. Encapsulates that in parens to place a copy on the pipeline. Then uses the comma operator to create an array of pre-decremented $n lines of #,spaces,#. Those are left on the pipeline. Then places $z again on the pipeline. Output via implicit Write-Output at the end introduces a newline between elements, so we get that for free. Since the OP's code doesn't work for input n <= 1, I took that to mean we don't need to support input 1, either. ### Examples PS C:\Tools\Scripts\golfing> 2..6|%{"$_";.\draw-a-hollow-square.ps1 $_;""} 2 ## ## 3 ### # # ### 4 #### # # # # #### 5 ##### # # # # # # ##### 6 ###### # # # # # # # # ######  • You can knock another byte off: param($n)($z='#'*$n--);,("#$(' '*--$n)#")*$n;$z – JohnLBevan Nov 8 '16 at 19:51
• @JohnLBevan Good idea with the script block. Thanks! – AdmBorkBork Nov 8 '16 at 19:52

# C, 98 bytes

f(n,i){i=n*(n+1);while(i--){putchar(i%(n+1)==n?10:i<n||i>n*n-1||i%(n+1)==0||i%(n+1)==n-1?35:32);}}


Usage:

f(5)


# 05AB1E, 20 bytes

'#×D¹Íð×'#.ø¹Í×sJ¹ä»


Try it online!

Or 18 bytes if we can ignore 1 <= n:

F„ #N¹<%_è¹Í×'#.ø,


Try it online!

# WinDbg, 206200182 170 bytes

.if@$t0{r$t3=2000000;f@$t3 L@$t0 23;f2*@$t3 L@$t0 20;eb2*@$t3 23;eb2*@$t3+@$t0-1 23;da@$t3 L@$t0;j1<@$t0'.for(r$t1=@$t0-2;@$t1;r$t1=@$t1-1){da2*@$t3 L@$t0};da@$t3 L@$t0'}  -6 bytes from removing parens from .if and using j instead of second .if -18 bytes by using f instead of a .for to construct the strings. -12 bytes by not NULL-terminating strings, instead passing length to da Input is passed in through the pseudo-register $t0 (eg r $t0 = 5; {above-code}). Explanation: .if @$t0                                                *Verify width($t0) at least 1 { *(registers have unsigned values) r$t3 = 2000000;                                    *Set $t3 to address where the *string will be constructed f @$t3 L@$t0 23; *Put width($t0) '#' at 2000000($t3) f 2 * @$t3 L@$t0 20; *Put width($t0) ' ' at 4000000(2*$t3) eb 2 * @$t3 23;                                     *Put '#' on left of ' ' string
eb 2 * @$t3 + @$t0 - 1 23;                          *Put '#' on right of ' ' string
da @$t3 L@$t0;                                      *Print the top of the box
j 1 < @$t0 *If width($t1) at least 2
'
.for (r $t1 = @$t0 - 2; @$t1; r$t1 = @$t1 - 1) *Loop width($t0)-2 times to...
{
da 2 * @$t3 L@$t0                           *...print the sides of the box
};
da @$t3 L@$t0                                   *Print the bottom of the box
'
}


Sample output:

0:000> r$t0=0 0:000> .if@$t0{r$t3=2000000;f@$t3 L@$t0 23;f2*@$t3 L@$t0 20;eb2*@$t3 23;eb2*@$t3+@$t0-1 23;da@$t3 L@$t0;j1<@$t0'.for(r$t1=@$t0-2;@$t1;r$t1=@$t1-1){da2*@$t3 L@$t0};da@$t3 L@$t0'}

0:000> r$t0=1 0:000> .if@$t0{r$t3=2000000;f@$t3 L@$t0 23;f2*@$t3 L@$t0 20;eb2*@$t3 23;eb2*@$t3+@$t0-1 23;da@$t3 L@$t0;j1<@$t0'.for(r$t1=@$t0-2;@$t1;r$t1=@$t1-1){da2*@$t3 L@$t0};da@$t3 L@$t0'}
Filled 0x1 bytes
Filled 0x1 bytes
02000000  "#"

0:000> r$t0=2 0:000> .if@$t0{r$t3=2000000;f@$t3 L@$t0 23;f2*@$t3 L@$t0 20;eb2*@$t3 23;eb2*@$t3+@$t0-1 23;da@$t3 L@$t0;j1<@$t0'.for(r$t1=@$t0-2;@$t1;r$t1=@$t1-1){da2*@$t3 L@$t0};da@$t3 L@$t0'}
Filled 0x2 bytes
Filled 0x2 bytes
02000000  "##"
02000000  "##"

0:000> r$t0=5 0:000> .if@$t0{r$t3=2000000;f@$t3 L@$t0 23;f2*@$t3 L@$t0 20;eb2*@$t3 23;eb2*@$t3+@$t0-1 23;da@$t3 L@$t0;j1<@$t0'.for(r$t1=@$t0-2;@$t1;r$t1=@$t1-1){da2*@$t3 L@$t0};da@$t3 L@$t0'}
Filled 0x5 bytes
Filled 0x5 bytes
02000000  "#####"
04000000  "#   #"
04000000  "#   #"
04000000  "#   #"
02000000  "#####"


# JavaScript, 61 58 bytes

Saved 3 bytes thanks to @lmis!

n=>(b='#'[r='repeat'](n))+
#${' '[r](n-=2)}#[r](n)+ +b  (Doesn't handle 0 or 1) For 13 extra bytes (at 71 bytes), you can! n=>n?n-1?(b='#'[r='repeat'](n))+ #${' '[r](n-=2)}#[r](n)+
+b:'#':''


These solutions are fairly simple: they do a lot of storage to not repeat themselves to save a few bytes. Unminified without the variablsm it would look like:

n => // Anonymous function definition (Param n is the size)
'#'.repeat(n) +      // # n times to form the top

#${' '.repeat(n - 2)}# // Followed by a newline followed by a hash and n - 2 spaces and // another hash to make one of the middle lines .repeat(n - 2) + // The above middle lines repeated n - 2 times '#'.repeat(n) // Followed by the top line again  ### Try it! <script type="text/babel">var f=n=>n?n-1?(b='#'[r='repeat'](n))+\n#${' '[r](n-=2)}#[r](n)+\n+b:'#':'',b,r;function c(){document.getElementById('pre').textContent = f(+document.getElementById('input').value);}</script><input id="input" onkeydown="c();" onkeyup="c();" onchange="c();" onclick="c();" placeholder="Size"><pre id="pre"></pre>

• By adding !n?'':n==1?'#':, an extra 15 bytes at the beginning of the function body, you can handle inputs 0 and 1. – Kayla Nov 8 '16 at 5:12
• n=>(b='#'[r='repeat'](n)) and then #${" "[r](n-=2)} etc. saves you 3 bytes by avoiding to repeat repeat :) – Lmis Nov 8 '16 at 10:15 # Python, 109 bytes n=int(input()) for x in range(n): r=list(' '*n);r=r[-1]='#' if x%(n-1)==0:r='#'*n print("".join(r))  • You can replace list(' '*n) with [' ']*n. You can also replace x%(n-1) with x%~-n – Wheat Wizard Nov 7 '16 at 14:58 • also, if you turn the for block into a list comprehension you can save more than 20 bytes – Rod Nov 7 '16 at 15:11 • Also, swith to Python 2, drop int() and the brackets around print. – Artyer Nov 7 '16 at 19:16 • Use <1 instead of ==0. – mbomb007 Nov 7 '16 at 19:55 # Ruby, 39 bytes ->n{puts a=?#*n,[?#+' '*(n-=2)+?#]*n,a}  Turns out to be shorter this way than all the fancy stuff I was trying. Be advised that this doesn't handle 0 or 1 at all. ## Python 2, 50 bytes m=input()-2 for c in'#'+' '*m+'#':print'#'+m*c+'#'  Works for n>=2. Prints each line with a pound sign, n-2 of the appropriate symbol, then another pound sign. Aliasing the pound symbol gives same length: m=input()-2;p='#' for c in p+' '*m+p:print p+m*c+p  Other attempts: lambda n:'#'*n+('\n#'+' '*(n-2)+'#')*(n-2)+'\n'+'#'*n lambda n:'#'*n+'\n#%s#'%((n-2)*' ')*(n-2)+'\n'+'#'*n lambda n:'\n'.join(['#'*n]+['#'+' '*(n-2)+'#']*(n-2)+['#'*n]) n=input();s='#'+' '*(n-2)+'#' for c in s:print[s,'#'*n][c>' '] s='##'+' #'*(input()-2)+'##' for c in s[::2]:print s[c>' '::2] s='#'+' '*(input()-2)+'#' for c in s:print s.replace(' ',c)  ## Haskell, 49 bytes n%b='#':(b<$[3..n])++"#\n"
f n=(n%)=<<init(n%' ')


Works for n>=2. Defines the operation of sandwiching a character between # for an n-character newline-terminated string, then applies it twice to make a 2D grid.

Call like:

*Main> putStrLn$f 5 ##### # # # # # # #####  # C, 83828078 77 Bytes i,j;f(n){for(i=n;i--;puts(""))for(j=n;j--;putchar(i*j&&i^n-1&&j^n-1?32:35));}  Sneak in a multiply and save a byte... i,j;f(n){for(i=n;i--;puts(""))for(j=n;j--;putchar(i&&j&&i^n-1&&j^n-1?32:35));}  Also count down j and save a few more... i,j;f(n){for(i=n;i--;puts(""))for(j=0;j++<n;putchar(i&&j^1&&i^n-1&&j^n?32:35));}  Count down i from n to zero and save a few bytes... i,j;f(n){for(i=0;i++<n;puts(""))for(j=0;j++<n;putchar(i^1&&j^1&&i^n&&j^n?32:35));}  A bit easier to understand and 1 byte more i,j;f(n){for(i=0;i++<n;puts(""))for(j=0;j++<n;putchar(i==1|i==n|j==1|j==n?35:32));}  • Do you need && instead of &? – corvus_192 Nov 7 '16 at 20:56 • Yes, it needs to be logical &. I can use multiply but it requires too many parenthesis... – cleblanc Nov 7 '16 at 21:23 # Groovy, 51 50 bytes {n->a="*"*n+"\n";n-=2;print(a+"*${' '*n}*\n"*n+a)}


# PHP, 81 69 bytes

for($n=-1+$i=$argv;$i--;)echo str_pad("#",$n," #"[$i%$n<1]),"#\n";  Run with -r; provide input as argument. Throws a DivisionByZeroError for input=1. # R, 68 70 bytes Works for n > 1. Thanks to @Billywob for a couple of bytes swapping out the array for a matrix. cat(rbind(b<-'#',cbind(b,matrix(' ',n<-scan()-2,n),b),b,' '),sep='')  Uses rbind and cbind to put rows and columns of #'s around an n-2 square matrix of spaces. Newlines are bound to the rows as well. The newline in the source is significant. Input is from STDIN • Nice! I had no idea that a newline in a string implicitly adds \n. You could save two bytes by using matrix instead of array though. – Billywob Nov 8 '16 at 8:54 # Common Lisp, 150 130 bytes -20 thanks to @Cyoce and @AlexL. (defun s(v)(format t"~v,,,vA~%"v #\# #\#)(dotimes(h(- v 2))(format t"~v,,,vA~A~%"(- v 1)#\ #\# #\#))(format t"~v,,,vA"v #\# #\#))  Usage: * (s 5) ##### # # # # # # #####  Basically uses format twice for the top and bottom and a loop for the rows in between. The format call for the top and bottom outputs a line starting with # and padded to the appropriate width with #s. The format call for the rows in between works similarly, except the padding is spaces and a # gets printed at the end of the line. Note: I'm rather new to Lisp and expect to have a lot of room for improvement on this. • Why not name it s? Or do am anonymous function? – Cyoce Dec 2 '16 at 0:52 • I don't know Lisp, but are all of the spaces between a word and an open bracket to its right necessary? Like, does it have to be dotimes (h (- v 2)) or could it be dotimes(h(- v 2))? – HyperNeutrino Dec 2 '16 at 2:12 • @AlexL. yeah, there are a lot of opportunities for improvement here. A ton of whitespace can be removed between parentheses and other symbols. I'll just do that really quickly – artificialnull Dec 2 '16 at 2:23 ## Haskell, 67 bytes l#n=l<$[1..n]
f n=unlines$'#'#n:('#':' '#(n-2)++"#")#(n-2)++['#'#n]  Usage example: Prelude> putStrLn$ f 4
####
#  #
#  #
####


How it works:

l#n=l<$[1..n] -- helper function that makes n copies of l '#'#n -- make a string of n copies of #, followed by #(n-2) -- n-2 copies of '#':' '#(n-2)++"#" -- # followed by n-2 times spaces, followed by # ['#'#n] -- and a final string with n copies of # unlines -- join with newlines in-between  # Jelly, 13, bytes ,þ%µỊṀ€€ị⁾# Y  ### How? ,þ%µỊṀ€€ị⁾# Y - Main link: n þ - outer product with , - pair: [[[1,1],[2,1],...,[n,1]],[[1,2],[2,2],...,[n,2]], ... ,[[1,n],[2,n],...,[n,n]]] % - mod n: [[[1,1],[2,1],...,[0,1]],[[1,2],[2,2],...,[0,2]], ... ,[[1,0],[2,0],...,[0,0]]] µ - monadic chain separation Ị - abs(z)<=1: [[[1,1],[0,1],...,[1,1]],[[1,0],[0,0],...,[1,0]], ... ,[[1,1],[0,1],...,[1,1]]] €€ - for each for each Ṁ - maximum: [[1, 1, ...,1], [1, 0, ..., 1], ... ,[1, 1, ..., 1] ] ị - index into (1 based) ⁾# - "# ": ["##...#","# ...#", ...,"##...#"] Y - join with line feeds  ## Pip, 16 bytes 15 bytes of code, +1 for -n flag. (Y_Xa-2WR'#s)My  Works for input >= 2. Try it online! ### Explanation of somewhat ungolfed version First, we define a function y that takes a string argument, repeats it a-2 times (where a is the first command-line input), and wraps the result in #. Y _ X a-2 WR '# _ Identity function X a-2 String-repeated by a-2 WR '# Wrapped in # Y Yank the resulting function into y  Next, we apply this function twice--once normally, then again with map--to obtain the square as a list of strings: y M (y s) (y s) Call function y with s (preinitialized to " ") as argument y M Map y to each character of the resulting string  For input of 4, (y s) results in "# #" and y M (y s) in ["####"; "# #"; "# #"; "####"]. This latter value is then printed, with the -n flag causing it to be newline-separated. ### Golfing tricks To get from the ungolfed to the golfed version: • Remove spaces. • Y is an operator, which means we can use it in an expression. Instead of Y... followed by (ys), we can just do (Y...s). • The problem is, we have to yank the function before we reference it again as y; so yM(Y_Xa-2WR'#s) won't work. Solution: swap the operands of the Map operator. As long as one of them is a function and the other is an iterable type, it doesn't matter what order they come in. ## Racket 113 bytes (let*((d display)(g(λ()(for((i n))(d"#")))))(g)(d"\n")(for((i(- n 2)))(d"#")(for((i(- n 2)))(d" "))(d"#\n"))(g))  Ungolfed: (define (f n) (let* ((d display) (g (λ () (for ((i n)) (d "#")) (d "\n")))) (g) (for ((i (- n 2))) (d "#") (for ((i (- n 2))) (d " ") ) (d "#\n")) (g)))  Testing: (f 5)  Output: ##### # # # # # # #####  # SpecBAS - 57 bytes 1 INPUT n: a$="#"*n,n-=2,b$="#"+" "*n+"#"#13: ?a$'b$*n;a$


? is shorthand for PRINT, #13 is carriage return which can be tacked on to the end of a string without needing a + to join them.

The apostrophe moves print cursor down one line.

# Stuck, 29 27 Bytes

Pretty darn long for a "golfing" language, but I have forgotten how a lot of it works :P

i_2-_u'#*N+_'#' u*'#N+++u*u


Explanation:

i_2-_u                           # take input and triplicate, subtracting 2 (5 -> [3,3,5])
'#*N+_                     # create the top and bottom rows
'#' u*'#N+++u*       # create input - 2 copies of middle rows
u      # rotate left 1 to get correct order, implicit output


# C#, 154 152 bytes

Golfed:

void F(int n){Console.Write($"{new string('#',n)}\n");for(int i=2;i<n;i++)Console.Write($"#{new string(' ',n-2)}#\n");Console.Write(new string('#',n));}


Ungolfed:

    void F(int n)
{
Console.Write($"{new string('#', n)}\n"); for (int i = 2; i < n; i++) Console.Write($"#{new string(' ', n - 2)}#\n");

Console.Write(new string('#', n));
}


EDIT1: Loop range optimization.

## Lithp, 117 bytes

Line split in two for readability:

#N::((var X (repeat "#" N))(print X)(each (seq 3 N) (scope #X::((print (+ "#"
(repeat " " (- N 2)) "#")))))(print X))


Sample usage:

% square.lithp
(
(import "lists")
(def s #N::((var X (repeat "#" N))(print X)(each (seq 3 N) (scope #X::((print (+ "#" (repeat " " (- N 2)) "#")))))(print X)))
(s 10)
)

Output:
\$ ./run square.lithp
##########
#        #
#        #
#        #
#        #
#        #
#        #
#        #
#        #
##########